备份CatanBuilding瘦身独立工程
This commit is contained in:
44
Assets/Scripts/Core/CameraScroller.cs
Normal file
44
Assets/Scripts/Core/CameraScroller.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using System;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
public class CameraScroller : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
|
||||
{
|
||||
public bool isDragging { get; private set; }
|
||||
|
||||
float _yMax = 4.5f;
|
||||
float _yMin = -1f;
|
||||
|
||||
public void OnBeginDrag(PointerEventData eventData)
|
||||
{
|
||||
isDragging = true;
|
||||
}
|
||||
|
||||
public void OnDrag(PointerEventData eventData)
|
||||
{
|
||||
var main_cam = Camera.main;
|
||||
|
||||
if (main_cam != null)
|
||||
{
|
||||
var pos = main_cam.transform.position;
|
||||
var new_y = pos.y;
|
||||
new_y -= eventData.delta.y * 0.01f;
|
||||
pos.y = Mathf.Clamp(new_y, _yMin, _yMax);
|
||||
|
||||
main_cam.transform.position = pos;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnEndDrag(PointerEventData eventData)
|
||||
{
|
||||
isDragging = false;
|
||||
}
|
||||
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Core/CameraScroller.cs.meta
Normal file
11
Assets/Scripts/Core/CameraScroller.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 579052b1391d8f6479d60cf35900d4ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
162
Assets/Scripts/Core/CustomServerMgr.cs
Normal file
162
Assets/Scripts/Core/CustomServerMgr.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using asap.core;
|
||||
using LitJson;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
public interface ICustomServerMgr
|
||||
{
|
||||
Task<string> GetStringAsync(string url);
|
||||
Task<string> CustomServerPost(string url, string bodyString, string contentType = "application/json");
|
||||
Task<string> AccountRequest(string url, object data);
|
||||
Task<string> EventRequest(string url, object data);
|
||||
Task<string> ClubRequest(string url, object data);
|
||||
Task<string> BombRequest(string url, object data);
|
||||
Task<string> DuelRequest(string url, object data);
|
||||
Task<string> CommonDataRequest(string url, object data);
|
||||
Task<string> FriendRequest(string url, object data);
|
||||
Task<T> EventPartnerRequest<T>(string url, object data = null);
|
||||
CookieContainer Cookie { get; }
|
||||
}
|
||||
|
||||
public class CustomServerMgr : ICustomServerMgr
|
||||
{
|
||||
IConfig config { get; set; }
|
||||
|
||||
//网络客户端
|
||||
HttpClient client;
|
||||
|
||||
private CookieContainer _cookie;
|
||||
public CookieContainer Cookie => _cookie ?? throw new System.NullReferenceException();
|
||||
|
||||
public CustomServerMgr(IConfig config)
|
||||
{
|
||||
this.config = config;
|
||||
|
||||
var httpClientHandler = new HttpClientHandler();
|
||||
_cookie = new CookieContainer();
|
||||
httpClientHandler.CookieContainer = _cookie;
|
||||
client = new HttpClient(httpClientHandler);
|
||||
|
||||
client.BaseAddress =
|
||||
new System.Uri(config.Get<string>(GConstant.K_Event_API_URL,
|
||||
"http://192.168.9.101:5292/"));
|
||||
client.Timeout = TimeSpan.FromSeconds(15);
|
||||
}
|
||||
|
||||
public async Task<string> CustomServerPost(string url, string bodyString,
|
||||
string contentType = "application/json")
|
||||
{
|
||||
try
|
||||
{
|
||||
//#if UNITY_EDITOR
|
||||
// Debug.Log("CustomServerPost url:" + url);
|
||||
// Debug.Log("CustomServerPost bodyString:" + bodyString);
|
||||
//#endif
|
||||
var content = new StringContent(bodyString, Encoding.UTF8, "application/json");
|
||||
var response = await client.PostAsync(url, content);
|
||||
string result = await response.Content.ReadAsStringAsync();
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
||||
{
|
||||
//GameDebug.Log("CustomServerPost result:" + result.ToString());
|
||||
return result;
|
||||
}
|
||||
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
||||
{
|
||||
GContext.Publish(new game.EvtAPISvrUnauthorized());
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError(response.StatusCode.ToString() + "+++CustomServerPost error:" +
|
||||
result.ToString() + "+++CustomServerPost url:" + url + ":" +
|
||||
bodyString);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("CustomServerPost error:" + e.Message + "---CustomServerPost url:" +
|
||||
url + ":" + bodyString + "\n" + e.StackTrace);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> GetStringAsync(string url)
|
||||
{
|
||||
var response = await client.GetAsync(url);
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
GContext.Publish(new game.EvtAPISvrUnauthorized());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<string> AccountRequest(string url, object data)
|
||||
{
|
||||
return await CustomServerPost($"account/{url}",
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject(data));
|
||||
}
|
||||
|
||||
public async Task<string> EventRequest(string url, object data)
|
||||
{
|
||||
return await CustomServerPost($"event/{url}",
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject(data));
|
||||
}
|
||||
|
||||
public async Task<string> ClubRequest(string url, object data)
|
||||
{
|
||||
return await CustomServerPost($"club/{url}",
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject(data));
|
||||
}
|
||||
|
||||
public async Task<string> BombRequest(string url, object data)
|
||||
{
|
||||
return await CustomServerPost($"bomb/{url}",
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject(data));
|
||||
}
|
||||
|
||||
public async Task<string> CommonDataRequest(string url, object data)
|
||||
{
|
||||
return await CustomServerPost($"commondata/{url}",
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject(data));
|
||||
}
|
||||
|
||||
public async Task<string> DuelRequest(string url, object data)
|
||||
{
|
||||
return await CustomServerPost($"duel/{url}",
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject(data));
|
||||
}
|
||||
|
||||
public async Task<string> FriendRequest(string url, object data)
|
||||
{
|
||||
return await CustomServerPost($"friend/{url}",
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject(data));
|
||||
}
|
||||
|
||||
public async Task<T> EventPartnerRequest<T>(string url, object data = null)
|
||||
{
|
||||
var body = Newtonsoft.Json.JsonConvert.SerializeObject(data);
|
||||
var responseString = await CustomServerPost($"eventpartner/{url}", body);
|
||||
try
|
||||
{
|
||||
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(responseString);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Debug.LogError(
|
||||
$"<color=red>[EventPartner] Response {responseString} failed to be deserialized: {e.Message}</color>");
|
||||
return default(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Core/CustomServerMgr.cs.meta
Normal file
11
Assets/Scripts/Core/CustomServerMgr.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9344f5533a12764aa95085ab91f05a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
381
Assets/Scripts/Core/DoTweenExtension.cs
Normal file
381
Assets/Scripts/Core/DoTweenExtension.cs
Normal file
@@ -0,0 +1,381 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using DG.Tweening;
|
||||
using GameCore;
|
||||
using asap.core;
|
||||
|
||||
public static class DoTweenExtension
|
||||
{
|
||||
public static void Popup(this Transform rec_trans, TweenCallback complete_action = null,bool isUnScale = false)
|
||||
{
|
||||
/*rec_trans.localScale = Vector3.one;
|
||||
rec_trans.DOKill();
|
||||
var t = rec_trans.DOPunchScale(new Vector3(0.1f, 0.1f, 1), 0.3f);*/
|
||||
rec_trans.localScale = new Vector3(0.5f, 0.5f, 1);// Vector3.zero;
|
||||
rec_trans.DOKill();
|
||||
var t = rec_trans.DOScale(1, 0.3f);
|
||||
t.SetEase(Ease.OutBack);
|
||||
|
||||
if (isUnScale)
|
||||
{
|
||||
t.SetUpdate(true);
|
||||
}
|
||||
|
||||
if (complete_action != null)
|
||||
{
|
||||
t.OnComplete(complete_action);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShrinkDown(this Transform rec_trans, TweenCallback complete_action = null,bool isUnScale = false)
|
||||
{
|
||||
rec_trans.DOKill();
|
||||
var t = rec_trans.DOScale(0.5f, 0.3f).SetEase(Ease.InBack);
|
||||
|
||||
if (isUnScale)
|
||||
{
|
||||
t.SetUpdate(true);
|
||||
}
|
||||
|
||||
if (complete_action != null)
|
||||
{
|
||||
t.OnComplete(complete_action);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Popup(this Transform t, Image mask, TweenCallback fun = null)
|
||||
{
|
||||
t.localScale = new Vector3(0.5f, 0.5f, 1);
|
||||
t.DOKill();
|
||||
var x = t.DOScale(1, 0.3f).SetEase(Ease.OutBack).SetUpdate(true);
|
||||
if(mask != null)
|
||||
{
|
||||
mask.DOFade(0f,0f).SetUpdate(true);
|
||||
mask.DOFade(0.9f,0.1f).SetUpdate(true);
|
||||
}
|
||||
if (fun != null)
|
||||
{
|
||||
x.OnComplete(fun);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ShrinkDown(this Transform t, Image mask, TweenCallback fun = null)
|
||||
{
|
||||
t.DOKill();
|
||||
var x = t.DOScale(0.5f, 0.3f).SetEase(Ease.InBack).SetUpdate(true);
|
||||
if(mask != null)
|
||||
{
|
||||
mask.DOFade(0f,0.3f).SetUpdate(true);
|
||||
}
|
||||
if (fun != null)
|
||||
{
|
||||
x.OnComplete(fun);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PopupByCanvasGroup(this Transform rec_trans, TweenCallback complete_action = null)
|
||||
{
|
||||
CanvasGroup cg = rec_trans.GetComponent<CanvasGroup>();
|
||||
if(cg == null)
|
||||
cg = rec_trans.gameObject.AddComponent<CanvasGroup>();
|
||||
rec_trans.DOKill();
|
||||
cg.alpha = 0.2f;
|
||||
rec_trans.localScale = new Vector3(0.33f, 0.33f, 1);
|
||||
|
||||
// var t = rec_trans.DOScale(1, 0.3f);
|
||||
// t.SetEase(Ease.OutBack);
|
||||
// t.SetUpdate(true);
|
||||
// var tw = cg.DOFade(1f,0.3f);
|
||||
// tw.SetUpdate(true);
|
||||
|
||||
// if (complete_action != null)
|
||||
// {
|
||||
// t.OnComplete(complete_action);
|
||||
// }
|
||||
}
|
||||
|
||||
public static void ShrinkDownByCanvasGroup(this Transform rec_trans, TweenCallback complete_action = null)
|
||||
{
|
||||
CanvasGroup cg = rec_trans.GetComponent<CanvasGroup>();
|
||||
if(cg == null)
|
||||
cg = rec_trans.gameObject.AddComponent<CanvasGroup>();
|
||||
|
||||
rec_trans.DOKill();
|
||||
cg.alpha = 1;
|
||||
rec_trans.localScale = new Vector3(1f, 1f, 1);
|
||||
|
||||
float f = 1f/60;
|
||||
// UnityEngine.Debug.Log("fff "+f + " " + Application.targetFrameRate);
|
||||
var tw = rec_trans.DOScale(1.1f,f * 11).OnComplete(()=>
|
||||
{
|
||||
var tw1 = rec_trans.DOScale(0.33f,f * 16);
|
||||
var tw2 = cg.DOFade(0f,f*16);
|
||||
tw1.SetUpdate(true);
|
||||
tw2.SetUpdate(true);
|
||||
|
||||
if (complete_action != null)
|
||||
{
|
||||
tw2.OnComplete(complete_action);
|
||||
}
|
||||
});
|
||||
tw.SetUpdate(true);
|
||||
}
|
||||
|
||||
public static void Shake(this RectTransform rec_trans)
|
||||
{
|
||||
rec_trans.localScale = Vector3.one;
|
||||
rec_trans.DOKill();
|
||||
rec_trans.DOPunchScale(Vector3.one, 0.3f, 5);
|
||||
}
|
||||
|
||||
public static void Shake(this Transform rec_trans)
|
||||
{
|
||||
rec_trans.localScale = Vector3.one;
|
||||
rec_trans.DOKill();
|
||||
rec_trans.DOPunchScale(Vector3.one, 0.3f, 5);
|
||||
}
|
||||
|
||||
public static void FlyingOut(this Text fade_text, Vector3 default_local_pos, Action on_complete = null)
|
||||
{
|
||||
var rec_trans = fade_text.rectTransform;
|
||||
|
||||
FlyingOutPosition(rec_trans, default_local_pos, on_complete);
|
||||
fade_text.DOFade(0, 1).From(1).SetEase(Ease.InOutSine);
|
||||
}
|
||||
|
||||
public static void FlyingOut(this CanvasGroup canvas_group, Vector3 default_local_pos, Action on_complete = null)
|
||||
{
|
||||
var rec_trans = canvas_group.GetComponent<RectTransform>();
|
||||
|
||||
if (rec_trans == null) return;
|
||||
|
||||
FlyingOutPosition(rec_trans, default_local_pos, on_complete);
|
||||
canvas_group.DOFade(0, 1).From(1).SetEase(Ease.InOutSine);
|
||||
}
|
||||
|
||||
public static void FlyingOutPosition(RectTransform rec_trans, Vector3 default_local_pos, Action on_complete = null)
|
||||
{
|
||||
rec_trans.gameObject.SetActiveAsNeed(true);
|
||||
rec_trans.DOKill();
|
||||
|
||||
var move_from = default_local_pos;
|
||||
var move_to = move_from;
|
||||
move_to.y += 200;
|
||||
|
||||
var t = rec_trans.DOLocalMove(move_to, 1f).SetEase(Ease.InOutSine).From(move_from);
|
||||
|
||||
t.OnComplete(() =>
|
||||
{
|
||||
rec_trans.gameObject.SetActiveAsNeed(false);
|
||||
rec_trans.localPosition = move_from;
|
||||
|
||||
if (on_complete != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
on_complete.Invoke();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GameDebug.LogError($"[DoTweenExtension]FlyingOutPosition: {ex.Message}");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Tween WorldMoveTo(this Transform flyobj, Transform target, float duration)
|
||||
{
|
||||
var end_pos = target.position;
|
||||
var tw = flyobj.DOMove(end_pos, duration);
|
||||
|
||||
if (tw != null)
|
||||
{
|
||||
tw.SetEase(Ease.InOutExpo);
|
||||
}
|
||||
|
||||
return tw;
|
||||
}
|
||||
|
||||
public static Tween MoveTo(this Transform move_obj, Transform target, float duration, Ease ease = Ease.InOutExpo)
|
||||
{
|
||||
var target_pos = target.position;
|
||||
|
||||
return move_obj.MoveTo(target_pos, duration, ease);
|
||||
}
|
||||
|
||||
public static Tween MoveTo(this Transform move_obj, Vector3 target_local_pos, float duration, Ease ease = Ease.InOutExpo)
|
||||
{
|
||||
var tw = move_obj.DOMove(target_local_pos, duration);
|
||||
|
||||
if (tw != null)
|
||||
{
|
||||
tw.SetEase(ease);
|
||||
}
|
||||
|
||||
return tw;
|
||||
}
|
||||
|
||||
public static Tween LocalMoveTo(this Transform move_obj, Transform target, float duration, Ease ease = Ease.InOutExpo)
|
||||
{
|
||||
var target_pos = target.position;
|
||||
|
||||
return move_obj.LocalMoveTo(target_pos, duration, ease);
|
||||
}
|
||||
|
||||
public static Tween LocalMoveTo(this Transform move_obj, Vector3 target_local_pos, float duration, Ease ease = Ease.InOutExpo)
|
||||
{
|
||||
var tw = move_obj.DOLocalMove(target_local_pos, duration); // Note: DOMove seems not hit the target position after finished
|
||||
|
||||
if (tw != null)
|
||||
{
|
||||
tw.SetEase(ease);
|
||||
}
|
||||
|
||||
return tw;
|
||||
}
|
||||
|
||||
public static Tween FlyTo(this Transform flyobj, Transform target, float duration, PathMode mode = PathMode.Full3D,bool isUnScale = false)
|
||||
{
|
||||
var start_pos = flyobj.position;
|
||||
start_pos.z = 0;
|
||||
var end_pos = target.position;
|
||||
end_pos.z = 0;
|
||||
var dir = end_pos - start_pos;
|
||||
var center = (end_pos + start_pos) * 0.5f;
|
||||
var off_v = Vector3.up;
|
||||
|
||||
if (Mathf.Abs(start_pos.x) < 10f)
|
||||
{
|
||||
off_v = Vector3.right;
|
||||
}
|
||||
|
||||
var ratio = Mathf.Abs(dir.y) / 650f;
|
||||
|
||||
var middle_pos = center + off_v * 400f * ratio;
|
||||
middle_pos.z = 0;
|
||||
var path = new Vector3[] { start_pos, middle_pos, end_pos };
|
||||
var tw = flyobj.DOPath(path, duration, PathType.CatmullRom, mode);
|
||||
if(isUnScale)
|
||||
tw.SetUpdate(true);
|
||||
|
||||
if (tw != null)
|
||||
{
|
||||
tw.SetEase(Ease.Linear);
|
||||
}
|
||||
|
||||
return tw;
|
||||
}
|
||||
|
||||
public static Tween FlyTo(this Transform flyobj, Transform target, Transform middle, float duration, PathMode mode = PathMode.Full3D,bool isUnScale = false)
|
||||
{
|
||||
var start_pos = flyobj.position;
|
||||
start_pos.z = 0;
|
||||
var end_pos = target.position;
|
||||
end_pos.z = 0;
|
||||
var middle_pos = middle.position;
|
||||
middle_pos.z = 0;
|
||||
|
||||
var path = new Vector3[] { start_pos, middle_pos, end_pos };
|
||||
var tw = flyobj.DOPath(path, duration, PathType.CatmullRom, mode);
|
||||
if(isUnScale)
|
||||
tw.SetUpdate(true);
|
||||
if (tw != null)
|
||||
{
|
||||
tw.SetEase(Ease.Linear);
|
||||
}
|
||||
|
||||
return tw;
|
||||
}
|
||||
|
||||
public static Tween FlyTo(this Transform flyobj, Vector3 target, Vector3 middle, float duration, PathMode mode = PathMode.Full3D,bool isUnScale = false)
|
||||
{
|
||||
var start_pos = flyobj.position;
|
||||
start_pos.z = 0;
|
||||
var end_pos = target;
|
||||
end_pos.z = 0;
|
||||
var middle_pos = middle;
|
||||
middle_pos.z = 0;
|
||||
|
||||
var path = new Vector3[] { start_pos, middle_pos, end_pos };
|
||||
var tw = flyobj.DOPath(path, duration, PathType.CatmullRom, mode);
|
||||
if(isUnScale)
|
||||
tw.SetUpdate(true);
|
||||
if (tw != null)
|
||||
{
|
||||
tw.SetEase(Ease.Linear);
|
||||
}
|
||||
|
||||
return tw;
|
||||
}
|
||||
|
||||
public static Tween FlyTo(this Transform flyobj, Vector3 target_pos, Vector3 middle_pos, float duration,bool isUnScale = false)
|
||||
{
|
||||
var start_pos = flyobj.position;
|
||||
start_pos.z = 0;
|
||||
|
||||
var path = new Vector3[] { start_pos, middle_pos, target_pos };
|
||||
var tw = flyobj.DOPath(path, duration, PathType.CatmullRom, PathMode.Full3D);
|
||||
if(isUnScale)
|
||||
tw.SetUpdate(true);
|
||||
if (tw != null)
|
||||
{
|
||||
tw.SetEase(Ease.Linear);
|
||||
}
|
||||
|
||||
return tw;
|
||||
}
|
||||
|
||||
public static Tween Flash(this Graphic target, float duration)
|
||||
{
|
||||
var t = DOTween.ToAlpha(() => target.color, x => target.color = x, 0, duration);
|
||||
t.SetTarget(target);
|
||||
t.SetLoops(-1, LoopType.Yoyo);
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Tween DOFadeAlpha(this Graphic target, float endValue, float duration)
|
||||
{
|
||||
var t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Tween DOFadeAlpha(this SpriteRenderer target, float endValue, float duration)
|
||||
{
|
||||
var t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Tween DOFadeAlpha(this TextMesh target, float endValue, float duration)
|
||||
{
|
||||
var t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Tween DOFadeAlpha(this CanvasGroup target, float endValue, float duration)
|
||||
{
|
||||
var t = DOTween.To(() => target.alpha, x => target.alpha = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
public static Tween DoCircularTop(this RectTransform target, float ridus, float duration, bool isIgnoreTimeScale = false)
|
||||
{
|
||||
float time = 0;
|
||||
Vector2 vector2 = new Vector2();
|
||||
var t = DOTween.To(() => time, x => time = x, 1, duration).OnUpdate(() =>
|
||||
{
|
||||
float b = time;
|
||||
b = (-b * 360 + 90) * Mathf.Deg2Rad;
|
||||
vector2.x = Mathf.Cos(b) * ridus;
|
||||
vector2.y = Mathf.Sin(b) * ridus;
|
||||
target.anchoredPosition = vector2;
|
||||
});
|
||||
if (isIgnoreTimeScale)
|
||||
t.SetUpdate(true);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Core/DoTweenExtension.cs.meta
Normal file
11
Assets/Scripts/Core/DoTweenExtension.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01ec160c2da27a9408bf02c3635f4394
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
902
Assets/Scripts/Core/GameEventMgr.cs
Normal file
902
Assets/Scripts/Core/GameEventMgr.cs
Normal file
@@ -0,0 +1,902 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameCore
|
||||
{
|
||||
public static class GameCoreEvents
|
||||
{
|
||||
public static readonly int GameStateEnd = 0;
|
||||
public static readonly int GameStateStart = 1;
|
||||
}
|
||||
|
||||
public class GameEventMgr
|
||||
{
|
||||
private static GameEventMgr _instance;
|
||||
public static GameEventMgr Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new GameEventMgr();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Init(bool is_debug_mode = false)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new GameEventMgr();
|
||||
}
|
||||
|
||||
_isDebugMode = is_debug_mode;
|
||||
|
||||
if(_isDebugMode)
|
||||
{
|
||||
Debug.Log($"[GameEventMgr]Init: Running in debug mode");
|
||||
}
|
||||
}
|
||||
|
||||
public static bool _isDebugMode = false;
|
||||
|
||||
struct DelegateGameObjectBonding
|
||||
{
|
||||
public GameObject gameObject;
|
||||
public Delegate listener;
|
||||
|
||||
public DelegateGameObjectBonding(GameObject game_object, Delegate del)
|
||||
{
|
||||
gameObject = game_object;
|
||||
listener = del;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Queue<List<Delegate>> _listenerListQueue = new Queue<List<Delegate>>();
|
||||
private readonly Queue<List<DelegateGameObjectBonding>> _listenerBondingListQueue = new Queue<List<DelegateGameObjectBonding>>();
|
||||
private readonly Dictionary<int, List<Delegate>> _eventTable = new Dictionary<int, List<Delegate>>();
|
||||
private readonly Dictionary<int, List<DelegateGameObjectBonding>> _eventObjTable = new Dictionary<int, List<DelegateGameObjectBonding>>();
|
||||
private readonly Dictionary<string, List<Delegate>> _strEventTable = new Dictionary<string, List<Delegate>>();
|
||||
private readonly Dictionary<string, List<DelegateGameObjectBonding>> _strEventObjTable = new Dictionary<string, List<DelegateGameObjectBonding>>();
|
||||
private readonly Dictionary<int, List<Delegate>> _pendingAddTable = new Dictionary<int, List<Delegate>>();
|
||||
private readonly Dictionary<int, List<DelegateGameObjectBonding>> _pendingObjAddTable = new Dictionary<int, List<DelegateGameObjectBonding>>();
|
||||
private readonly Dictionary<int, List<Delegate>> _pendingRemoveTable = new Dictionary<int, List<Delegate>>();
|
||||
private readonly Dictionary<int, List<DelegateGameObjectBonding>> _pendingObjRemoveTable = new Dictionary<int, List<DelegateGameObjectBonding>>();
|
||||
private readonly Dictionary<string, List<Delegate>> _pendingAddNameTable = new Dictionary<string, List<Delegate>>();
|
||||
private readonly Dictionary<string, List<DelegateGameObjectBonding>> _pendingObjAddNameTable = new Dictionary<string, List<DelegateGameObjectBonding>>();
|
||||
private readonly Dictionary<string, List<Delegate>> _pendingRemoveNameTable = new Dictionary<string, List<Delegate>>();
|
||||
private readonly Dictionary<string, List<DelegateGameObjectBonding>> _pendingObjRemoveNameTable = new Dictionary<string, List<DelegateGameObjectBonding>>();
|
||||
|
||||
// Using raising event list to prevent infinite loop call or changing delegate list
|
||||
private readonly List<int> _raisingEventIds = new List<int>();
|
||||
private readonly List<string> _raisingEventNames = new List<string>();
|
||||
|
||||
private GameEventMgr() { }
|
||||
|
||||
public void AddListener(int event_id, Action new_listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoAddListener(event_id, new_listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void AddListener<T>(int event_id, Action<T> new_listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoAddListener(event_id, new_listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void AddListener<T1, T2>(int event_id, Action<T1, T2> new_listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoAddListener(event_id, new_listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void AddListener<T1, T2, T3>(int event_id, Action<T1, T2, T3> new_listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoAddListener(event_id, new_listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void AddListener(string event_name, Action new_listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoAddListener(event_name, new_listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void AddListener<T>(string event_name, Action<T> new_listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoAddListener(event_name, new_listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void AddListener<T1, T2>(string event_name, Action<T1, T2> new_listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoAddListener(event_name, new_listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void AddListener<T1, T2, T3>(string event_name, Action<T1, T2, T3> new_listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoAddListener(event_name, new_listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void RemoveListener(int event_id, Action listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoRemoveListener(event_id, listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void RemoveListener<T>(int event_id, Action<T> listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoRemoveListener(event_id, listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void RemoveListener<T1, T2>(int event_id, Action<T1, T2> listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoRemoveListener(event_id, listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void RemoveListener<T1, T2, T3>(int event_id, Action<T1, T2, T3> listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoRemoveListener(event_id, listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void RemoveListener(string event_name, Action listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoRemoveListener(event_name, listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void RemoveListener<T>(string event_name, Action<T> listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoRemoveListener(event_name, listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void RemoveListener<T1, T2>(string event_name, Action<T1, T2> listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoRemoveListener(event_name, listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void RemoveListener<T1, T2, T3>(string event_name, Action<T1, T2, T3> listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
DoRemoveListener(event_name, listener, life_cycle_obj);
|
||||
}
|
||||
|
||||
public void Raise(int event_id)
|
||||
{
|
||||
DoRaise(event_id);
|
||||
}
|
||||
|
||||
public void Raise<T>(int event_id, T arg1)
|
||||
{
|
||||
DoRaise(event_id, arg1);
|
||||
}
|
||||
|
||||
public void Raise<T1, T2>(int event_id, T1 arg1, T2 arg2)
|
||||
{
|
||||
DoRaise(event_id, arg1, arg2);
|
||||
}
|
||||
|
||||
public void Raise<T1, T2, T3>(int event_id, T1 arg1, T2 arg2, T3 arg3)
|
||||
{
|
||||
DoRaise(event_id, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
public void Raise(string event_name)
|
||||
{
|
||||
DoRaise(event_name);
|
||||
}
|
||||
|
||||
public void Raise<T>(string event_name, T arg1)
|
||||
{
|
||||
DoRaise(event_name, arg1);
|
||||
}
|
||||
|
||||
public void Raise<T1, T2>(string event_name, T1 arg1, T2 arg2)
|
||||
{
|
||||
DoRaise(event_name, arg1, arg2);
|
||||
}
|
||||
|
||||
public void Raise<T1, T2, T3>(string event_name, T1 arg1, T2 arg2, T3 arg3)
|
||||
{
|
||||
DoRaise(event_name, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
public void ClearNullGameObjectListeners()
|
||||
{
|
||||
var etor = _eventObjTable.GetEnumerator();
|
||||
|
||||
while (etor.MoveNext())
|
||||
{
|
||||
var listeners = etor.Current.Value;
|
||||
|
||||
for (int i = 0; i < listeners.Count; i++)
|
||||
{
|
||||
if(listeners[i].gameObject == null)
|
||||
{
|
||||
listeners.RemoveAt(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var str_etor = _strEventObjTable.GetEnumerator();
|
||||
|
||||
while (str_etor.MoveNext())
|
||||
{
|
||||
var listeners = str_etor.Current.Value;
|
||||
|
||||
for (int i = 0; i < listeners.Count; i++)
|
||||
{
|
||||
if (listeners[i].gameObject == null)
|
||||
{
|
||||
listeners.RemoveAt(i--);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Delegate> SpawnDelegateList()
|
||||
{
|
||||
if(_listenerListQueue.Count > 0)
|
||||
{
|
||||
return _listenerListQueue.Dequeue();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new List<Delegate>();
|
||||
}
|
||||
}
|
||||
|
||||
private void DespawnDelegateList(List<Delegate> list)
|
||||
{
|
||||
if (list == null) return;
|
||||
|
||||
list.Clear();
|
||||
_listenerListQueue.Enqueue(list);
|
||||
}
|
||||
|
||||
private List<DelegateGameObjectBonding> SpawnDelegateBondingList()
|
||||
{
|
||||
if (_listenerBondingListQueue.Count > 0)
|
||||
{
|
||||
return _listenerBondingListQueue.Dequeue();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new List<DelegateGameObjectBonding>();
|
||||
}
|
||||
}
|
||||
|
||||
private void DespawnDelegateBondingList(List<DelegateGameObjectBonding> list)
|
||||
{
|
||||
if (list == null) return;
|
||||
|
||||
list.Clear();
|
||||
_listenerBondingListQueue.Enqueue(list);
|
||||
}
|
||||
|
||||
private bool DoAddListener(int event_id, Delegate new_listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
if (new_listener == null)
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoAddListener: Can't add empty listener for event {event_id}!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
|
||||
// If event is raising, add it into pending list
|
||||
if (_raisingEventIds.Contains(event_id))
|
||||
{
|
||||
if (life_cycle_obj != null)
|
||||
{
|
||||
if (!_pendingObjAddTable.TryGetValue(event_id, out var pending_listeners))
|
||||
{
|
||||
pending_listeners = SpawnDelegateBondingList();
|
||||
_pendingObjAddTable[event_id] = pending_listeners;
|
||||
}
|
||||
|
||||
pending_listeners.Add(new DelegateGameObjectBonding(life_cycle_obj, new_listener));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_pendingAddTable.TryGetValue(event_id, out var pending_listeners))
|
||||
{
|
||||
pending_listeners = SpawnDelegateList();
|
||||
_pendingAddTable[event_id] = pending_listeners;
|
||||
}
|
||||
|
||||
pending_listeners.Add(new_listener);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (life_cycle_obj != null)
|
||||
{
|
||||
if (!_eventObjTable.TryGetValue(event_id, out var listener_bondings))
|
||||
{
|
||||
listener_bondings = SpawnDelegateBondingList();
|
||||
_eventObjTable[event_id] = listener_bondings;
|
||||
}
|
||||
|
||||
if (listener_bondings.Count == 0 || listener_bondings[0].listener.GetType() == new_listener.GetType())
|
||||
{
|
||||
var bonding = new DelegateGameObjectBonding(life_cycle_obj, new_listener);
|
||||
|
||||
if (_isDebugMode && listener_bondings.Contains(bonding))
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoAddListener: Already in the list, will not add it again [{new_listener.Target}.{new_listener.Method?.Name}]");
|
||||
}
|
||||
else
|
||||
{
|
||||
listener_bondings.Add(bonding);
|
||||
}
|
||||
}
|
||||
else if (listener_bondings[0].listener.GetType() != new_listener.GetType())
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoAddListener: Attempting to add listener with inconsistent signature for event {event_id}. Current listeners type({listener_bondings[0].listener.GetType().Name}) != added type({new_listener.GetType().Name})");
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_eventTable.TryGetValue(event_id, out var listeners))
|
||||
{
|
||||
listeners = SpawnDelegateList();
|
||||
_eventTable[event_id] = listeners;
|
||||
}
|
||||
|
||||
if (listeners.Count == 0 || listeners[0].GetType() == new_listener.GetType())
|
||||
{
|
||||
if (_isDebugMode && listeners.Contains(new_listener))
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoAddListener: Already in the list, will not add it again [{new_listener.Target}.{new_listener.Method?.Name}]");
|
||||
}
|
||||
else
|
||||
{
|
||||
listeners.Add(new_listener);
|
||||
}
|
||||
}
|
||||
else if (listeners[0].GetType() != new_listener.GetType())
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoAddListener: Attempting to add listener with inconsistent signature for event {event_id}. Current listeners type({listeners[0].GetType().Name}) != added type({new_listener.GetType().Name})");
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool DoAddListener(string event_name, Delegate new_listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
if (new_listener == null)
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoAddListener: Can't add empty listener for event {event_name}!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
|
||||
// If event is raising, add it into pending list
|
||||
if (_raisingEventNames.Contains(event_name))
|
||||
{
|
||||
if (life_cycle_obj != null)
|
||||
{
|
||||
if (!_pendingObjAddNameTable.TryGetValue(event_name, out var pending_listeners))
|
||||
{
|
||||
pending_listeners = SpawnDelegateBondingList();
|
||||
_pendingObjAddNameTable[event_name] = pending_listeners;
|
||||
}
|
||||
|
||||
pending_listeners.Add(new DelegateGameObjectBonding(life_cycle_obj, new_listener));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_pendingAddNameTable.TryGetValue(event_name, out var pending_listeners))
|
||||
{
|
||||
pending_listeners = SpawnDelegateList();
|
||||
_pendingAddNameTable[event_name] = pending_listeners;
|
||||
}
|
||||
|
||||
pending_listeners.Add(new_listener);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (life_cycle_obj != null)
|
||||
{
|
||||
if (!_strEventObjTable.TryGetValue(event_name, out var listeners))
|
||||
{
|
||||
listeners = SpawnDelegateBondingList();
|
||||
_strEventObjTable[event_name] = listeners;
|
||||
}
|
||||
|
||||
if (listeners.Count == 0 || listeners[0].listener.GetType() == new_listener.GetType())
|
||||
{
|
||||
var bonding = new DelegateGameObjectBonding(life_cycle_obj, new_listener);
|
||||
|
||||
if (_isDebugMode && listeners.Contains(bonding))
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoAddListener: Already in the list, will not add it again [{new_listener.Target}.{new_listener.Method?.Name}]");
|
||||
}
|
||||
else
|
||||
{
|
||||
listeners.Add(bonding);
|
||||
}
|
||||
}
|
||||
else if (listeners[0].listener.GetType() != new_listener.GetType())
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoAddListener: Attempting to add listener with inconsistent signature for event {event_name}. Current listeners type({listeners[0].listener.GetType().Name}) != added type({new_listener.GetType().Name})");
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_strEventTable.TryGetValue(event_name, out var listeners))
|
||||
{
|
||||
listeners = SpawnDelegateList();
|
||||
_strEventTable[event_name] = listeners;
|
||||
}
|
||||
|
||||
if (listeners.Count == 0 || listeners[0].GetType() == new_listener.GetType())
|
||||
{
|
||||
if (_isDebugMode && listeners.Contains(new_listener))
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoAddListener: Already in the list, will not add it again [{new_listener.Target}.{new_listener.Method?.Name}]");
|
||||
}
|
||||
else
|
||||
{
|
||||
listeners.Add(new_listener);
|
||||
}
|
||||
}
|
||||
else if (listeners[0].GetType() != new_listener.GetType())
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoAddListener: Attempting to add listener with inconsistent signature for event {event_name}. Current listeners type({listeners[0].GetType().Name}) != added type({new_listener.GetType().Name})");
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool DoRemoveListener(int event_id, Delegate listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
if (listener == null)
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoRemoveListener: Can't remove empty listener for event {event_id}!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
|
||||
// If event is raising, add it into pending list
|
||||
if (_raisingEventIds.Contains(event_id))
|
||||
{
|
||||
if (life_cycle_obj != null)
|
||||
{
|
||||
if (!_pendingObjRemoveTable.TryGetValue(event_id, out var pending_listeners))
|
||||
{
|
||||
pending_listeners = SpawnDelegateBondingList();
|
||||
_pendingObjRemoveTable[event_id] = pending_listeners;
|
||||
}
|
||||
|
||||
pending_listeners.Add(new DelegateGameObjectBonding(life_cycle_obj, listener));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_pendingRemoveTable.TryGetValue(event_id, out var pending_listeners))
|
||||
{
|
||||
pending_listeners = SpawnDelegateList();
|
||||
_pendingRemoveTable[event_id] = pending_listeners;
|
||||
}
|
||||
|
||||
pending_listeners.Add(listener);
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (life_cycle_obj != null)
|
||||
{
|
||||
if (_eventObjTable.TryGetValue(event_id, out var listeners))
|
||||
{
|
||||
if (listeners.Count > 0)
|
||||
{
|
||||
listeners.Remove(new DelegateGameObjectBonding(life_cycle_obj, listener));
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (listeners.Count == 0)
|
||||
{
|
||||
DespawnDelegateBondingList(listeners);
|
||||
_eventObjTable.Remove(event_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_eventTable.TryGetValue(event_id, out var listeners))
|
||||
{
|
||||
if (listeners.Count > 0)
|
||||
{
|
||||
listeners.Remove(listener);
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (listeners.Count == 0)
|
||||
{
|
||||
DespawnDelegateList(listeners);
|
||||
_eventTable.Remove(event_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool DoRemoveListener(string event_name, Delegate listener, GameObject life_cycle_obj = null)
|
||||
{
|
||||
if (listener == null)
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoRemoveListener: Can't remove empty listener for event {event_name}!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
|
||||
// If event is raising, add it into pending list
|
||||
if (_raisingEventNames.Contains(event_name))
|
||||
{
|
||||
if (life_cycle_obj != null)
|
||||
{
|
||||
if (!_pendingObjRemoveNameTable.TryGetValue(event_name, out var pending_listeners))
|
||||
{
|
||||
pending_listeners = SpawnDelegateBondingList();
|
||||
_pendingObjRemoveNameTable[event_name] = pending_listeners;
|
||||
}
|
||||
|
||||
pending_listeners.Add(new DelegateGameObjectBonding(life_cycle_obj, listener));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_pendingRemoveNameTable.TryGetValue(event_name, out var pending_listeners))
|
||||
{
|
||||
pending_listeners = SpawnDelegateList();
|
||||
_pendingRemoveNameTable[event_name] = pending_listeners;
|
||||
}
|
||||
|
||||
pending_listeners.Add(listener);
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (life_cycle_obj != null)
|
||||
{
|
||||
if (_strEventObjTable.TryGetValue(event_name, out var listeners))
|
||||
{
|
||||
if (listeners.Count > 0)
|
||||
{
|
||||
listeners.Remove(new DelegateGameObjectBonding(life_cycle_obj, listener));
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (listeners.Count == 0)
|
||||
{
|
||||
DespawnDelegateBondingList(listeners);
|
||||
_strEventObjTable.Remove(event_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_strEventTable.TryGetValue(event_name, out var listeners))
|
||||
{
|
||||
if (listeners.Count > 0)
|
||||
{
|
||||
listeners.Remove(listener);
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (listeners.Count == 0)
|
||||
{
|
||||
DespawnDelegateList(listeners);
|
||||
_strEventTable.Remove(event_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void LogException(Exception ex, string event_tag, string method_name)
|
||||
{
|
||||
string msg = ex.Message;
|
||||
string stack_trace = ex.StackTrace;
|
||||
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
msg = ex.InnerException.Message;
|
||||
stack_trace = ex.InnerException.StackTrace;
|
||||
}
|
||||
|
||||
Debug.LogError($"[GameEventMgr]{method_name}: Event({event_tag}) {msg}\nStack Trace: {stack_trace}");
|
||||
}
|
||||
|
||||
private bool DoRaise(int event_id, params object[] args)
|
||||
{
|
||||
if (_raisingEventIds.Contains(event_id))
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoRaise: Can't raise event({event_id}) again inside the same event raising process!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
_raisingEventIds.Add(event_id);
|
||||
|
||||
if (_eventObjTable.TryGetValue(event_id, out var bond_listeners))
|
||||
{
|
||||
for (int i = 0; i < bond_listeners.Count; i++)
|
||||
{
|
||||
var bond_listener = bond_listeners[i];
|
||||
|
||||
if (bond_listener.gameObject != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
bond_listener.listener.Method.Invoke(bond_listener.listener.Target, args);
|
||||
result = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
bond_listeners.RemoveAt(i--);
|
||||
LogException(ex, $"{event_id}_Obj[{bond_listener.gameObject.name}]", "DoRaise");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bond_listeners.RemoveAt(i--);
|
||||
Debug.Log($"[GameEventMgr]DoRaise: Remove null GameObject listener ({event_id})!");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_eventTable.TryGetValue(event_id, out var listeners))
|
||||
{
|
||||
for (int i = 0; i < listeners.Count; i++)
|
||||
{
|
||||
var listener = listeners[i];
|
||||
|
||||
if(listener != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.Method.Invoke(listener.Target, args);
|
||||
result = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
listeners.RemoveAt(i--);
|
||||
LogException(ex, event_id.ToString(), "DoRaise");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_raisingEventIds.Remove(event_id);
|
||||
|
||||
if (_pendingObjAddTable.TryGetValue(event_id, out var add_bond_listeners))
|
||||
{
|
||||
if (add_bond_listeners != null && add_bond_listeners.Count > 0)
|
||||
{
|
||||
bond_listeners.AddRange(add_bond_listeners);
|
||||
DespawnDelegateBondingList(add_bond_listeners);
|
||||
}
|
||||
|
||||
_pendingObjAddTable.Remove(event_id);
|
||||
}
|
||||
|
||||
if (_pendingObjRemoveTable.TryGetValue(event_id, out var remove_bond_listeners))
|
||||
{
|
||||
if (remove_bond_listeners != null && remove_bond_listeners.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < remove_bond_listeners.Count; i++)
|
||||
{
|
||||
bond_listeners.Remove(remove_bond_listeners[i]);
|
||||
}
|
||||
|
||||
DespawnDelegateBondingList(remove_bond_listeners);
|
||||
}
|
||||
|
||||
_pendingObjRemoveTable.Remove(event_id);
|
||||
}
|
||||
|
||||
if (bond_listeners?.Count == 0)
|
||||
{
|
||||
DespawnDelegateBondingList(bond_listeners);
|
||||
_eventObjTable.Remove(event_id);
|
||||
}
|
||||
|
||||
if (_pendingAddTable.TryGetValue(event_id, out var add_listeners))
|
||||
{
|
||||
if (add_listeners != null && add_listeners.Count > 0)
|
||||
{
|
||||
listeners.AddRange(add_listeners);
|
||||
DespawnDelegateList(add_listeners);
|
||||
}
|
||||
|
||||
_pendingAddTable.Remove(event_id);
|
||||
}
|
||||
|
||||
if (_pendingRemoveTable.TryGetValue(event_id, out var remove_listeners))
|
||||
{
|
||||
if (remove_listeners != null && remove_listeners.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < remove_listeners.Count; i++)
|
||||
{
|
||||
listeners.Remove(remove_listeners[i]);
|
||||
}
|
||||
|
||||
DespawnDelegateList(remove_listeners);
|
||||
}
|
||||
|
||||
_pendingRemoveTable.Remove(event_id);
|
||||
}
|
||||
|
||||
if (listeners?.Count == 0)
|
||||
{
|
||||
DespawnDelegateList(listeners);
|
||||
_eventTable.Remove(event_id);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool DoRaise(string event_name, params object[] args)
|
||||
{
|
||||
if (_raisingEventNames.Contains(event_name))
|
||||
{
|
||||
Debug.LogError($"[GameEventMgr]DoRaise: Can't raise event({event_name}) again inside the same event raising process!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
_raisingEventNames.Add(event_name);
|
||||
|
||||
if (_strEventObjTable.TryGetValue(event_name, out var bond_listeners))
|
||||
{
|
||||
for (int i = 0; i < bond_listeners.Count; i++)
|
||||
{
|
||||
var bond_listener = bond_listeners[i];
|
||||
|
||||
if (bond_listener.gameObject != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
bond_listener.listener.Method.Invoke(bond_listener.listener.Target, args);
|
||||
result = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
bond_listeners.RemoveAt(i--);
|
||||
LogException(ex, $"{event_name}_Obj[{bond_listener.gameObject.name}]", "DoRaise");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bond_listeners.RemoveAt(i--);
|
||||
Debug.Log($"[GameEventMgr]DoRaise: Remove null GameObject listener ({event_name})!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_strEventTable.TryGetValue(event_name, out var listeners))
|
||||
{
|
||||
for (int i = 0; i < listeners.Count; i++)
|
||||
{
|
||||
var listener = listeners[i];
|
||||
|
||||
if (listener != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.Method.Invoke(listener.Target, args);
|
||||
result = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
listeners.RemoveAt(i--);
|
||||
LogException(ex, event_name, "DoRaise");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_raisingEventNames.Remove(event_name);
|
||||
|
||||
if (_pendingObjAddNameTable.TryGetValue(event_name, out var add_bond_listeners))
|
||||
{
|
||||
if (add_bond_listeners != null && add_bond_listeners.Count > 0)
|
||||
{
|
||||
bond_listeners.AddRange(add_bond_listeners);
|
||||
DespawnDelegateBondingList(add_bond_listeners);
|
||||
}
|
||||
|
||||
_pendingObjAddNameTable.Remove(event_name);
|
||||
}
|
||||
|
||||
if (_pendingObjRemoveNameTable.TryGetValue(event_name, out var remove_bond_listeners))
|
||||
{
|
||||
if (remove_bond_listeners != null && remove_bond_listeners.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < remove_bond_listeners.Count; i++)
|
||||
{
|
||||
bond_listeners.Remove(remove_bond_listeners[i]);
|
||||
}
|
||||
|
||||
DespawnDelegateBondingList(remove_bond_listeners);
|
||||
}
|
||||
|
||||
_pendingObjRemoveNameTable.Remove(event_name);
|
||||
}
|
||||
|
||||
if (bond_listeners?.Count == 0)
|
||||
{
|
||||
DespawnDelegateBondingList(bond_listeners);
|
||||
_strEventObjTable.Remove(event_name);
|
||||
}
|
||||
|
||||
if (_pendingAddNameTable.TryGetValue(event_name, out var add_listeners))
|
||||
{
|
||||
if (add_listeners != null && add_listeners.Count > 0)
|
||||
{
|
||||
listeners.AddRange(add_listeners);
|
||||
DespawnDelegateList(add_listeners);
|
||||
}
|
||||
|
||||
_pendingAddNameTable.Remove(event_name);
|
||||
}
|
||||
|
||||
if (_pendingRemoveNameTable.TryGetValue(event_name, out var remove_listeners))
|
||||
{
|
||||
if (remove_listeners != null && remove_listeners.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < remove_listeners.Count; i++)
|
||||
{
|
||||
listeners.Remove(remove_listeners[i]);
|
||||
}
|
||||
|
||||
DespawnDelegateList(remove_listeners);
|
||||
}
|
||||
|
||||
_pendingRemoveNameTable.Remove(event_name);
|
||||
}
|
||||
|
||||
if (listeners?.Count == 0)
|
||||
{
|
||||
DespawnDelegateList(listeners);
|
||||
_strEventTable.Remove(event_name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_eventTable.Clear();
|
||||
_eventObjTable.Clear();
|
||||
_strEventTable.Clear();
|
||||
_strEventObjTable.Clear();
|
||||
_pendingAddTable.Clear();
|
||||
_pendingObjAddTable.Clear();
|
||||
_pendingRemoveTable.Clear();
|
||||
_pendingObjRemoveTable.Clear();
|
||||
_pendingAddNameTable.Clear();
|
||||
_pendingObjAddNameTable.Clear();
|
||||
_pendingRemoveNameTable.Clear();
|
||||
_pendingObjRemoveNameTable.Clear();
|
||||
_raisingEventIds.Clear();
|
||||
_raisingEventNames.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Core/GameEventMgr.cs.meta
Normal file
11
Assets/Scripts/Core/GameEventMgr.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af0b2f5d34d2eef43999b48f9d3e0a54
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
31
Assets/Scripts/Core/GameEvents.cs
Normal file
31
Assets/Scripts/Core/GameEvents.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.Resources;
|
||||
|
||||
public static class GameEvents
|
||||
{
|
||||
public static readonly int EVENTS_START_ID = 100;
|
||||
|
||||
public static readonly int DownloadStart = EVENTS_START_ID++;
|
||||
public static readonly int DownloadTotalSize = EVENTS_START_ID++;
|
||||
public static readonly int DownloadingSingleFile = EVENTS_START_ID++;
|
||||
public static readonly int DownloadAssetProgress = EVENTS_START_ID++;
|
||||
public static readonly int DownloadAssetComplete = EVENTS_START_ID++;
|
||||
public static readonly int FinishDownloadSingleFile = EVENTS_START_ID++;
|
||||
|
||||
public static readonly int ApplicationFocus = EVENTS_START_ID++;
|
||||
public static readonly int ApplicationQuit = EVENTS_START_ID++;
|
||||
public static readonly int SetGameState = EVENTS_START_ID++;
|
||||
public static readonly int GameRestart = EVENTS_START_ID++;
|
||||
public static readonly int ShowErrorDialog = EVENTS_START_ID++;
|
||||
public static readonly int DeviceProfileChange = EVENTS_START_ID++;
|
||||
public static readonly int FinishUpdateEvent = EVENTS_START_ID++;
|
||||
public static readonly int LoggedIn = EVENTS_START_ID++;
|
||||
public static readonly int StageDraggerClick = EVENTS_START_ID++;
|
||||
public static readonly int FishCountChange = EVENTS_START_ID++;
|
||||
public static readonly int ShowHomeMap = EVENTS_START_ID++;
|
||||
public static readonly int HideHomeMap = EVENTS_START_ID++;
|
||||
public static readonly int FishingEvent = EVENTS_START_ID++;
|
||||
public static readonly int EventFishingPlay = EVENTS_START_ID++;
|
||||
public static readonly int Social_InfoClub = EVENTS_START_ID++;
|
||||
|
||||
public static readonly int EVENTS_END_ID = EVENTS_START_ID++;
|
||||
}
|
||||
11
Assets/Scripts/Core/GameEvents.cs.meta
Normal file
11
Assets/Scripts/Core/GameEvents.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b033b66c2c06ed240b0f43d2520b1bd1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
436
Assets/Scripts/Core/GlobalUtils.cs
Normal file
436
Assets/Scripts/Core/GlobalUtils.cs
Normal file
@@ -0,0 +1,436 @@
|
||||
//#define EDITOR_GAMEVIEW_CHANGE_ENABLE
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using GameCore;
|
||||
using asap.core;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
public class GlobalUtils
|
||||
{
|
||||
public static string gameVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
return Application.version;
|
||||
#else
|
||||
return string.Format("{0}.{1}", Application.version, Application.buildGUID.GetHashCode().ToString("x"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static T StringToEnum<T>(string modestr, T defaultValue) where T : Enum
|
||||
{
|
||||
foreach (T mode in Enum.GetValues(typeof(T)))
|
||||
{
|
||||
if (mode.ToString() == modestr)
|
||||
return mode;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public static bool SaveFile(string content, string destPath)
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(content);
|
||||
return SaveFile(bytes, destPath);
|
||||
}
|
||||
|
||||
public static bool SaveFile(Byte[] bytes, string destPath)
|
||||
{
|
||||
if (bytes == null || string.IsNullOrEmpty(destPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
int index = destPath.LastIndexOf("/");
|
||||
string directory = destPath.Substring(0, index);
|
||||
|
||||
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GameDebug.LogError("[GlobalUtils]SaveFile: {0}", ex.Message);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (Directory.Exists(directory) && !File.Exists(destPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var file = File.Create(destPath)) { }
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GameDebug.LogError("[GlobalUtils]SaveFile: {0}", ex.Message);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(destPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.WriteAllBytes(destPath, bytes);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
GameDebug.LogError("[GlobalUtils]SaveFile: {0}", ex.Message);
|
||||
result = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GameDebug.LogError("[GlobalUtils]SaveFile: {0}", ex.Message);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
MessageDialog.ShowSomethingWrong();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static byte[] AesEncrypt(byte[] array, string key)
|
||||
{
|
||||
if (array == null || array.Length <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var toEncryptArray = array;
|
||||
var rm = new System.Security.Cryptography.RijndaelManaged
|
||||
{
|
||||
Key = Encoding.UTF8.GetBytes(key),
|
||||
Mode = System.Security.Cryptography.CipherMode.ECB,
|
||||
Padding = System.Security.Cryptography.PaddingMode.PKCS7
|
||||
};
|
||||
|
||||
var cTransform = rm.CreateEncryptor();
|
||||
var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
public static byte[] AesDecrypt(byte[] array, string key)
|
||||
{
|
||||
if (array == null || array.Length <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var toEncryptArray = array;
|
||||
var rm = new System.Security.Cryptography.RijndaelManaged
|
||||
{
|
||||
Key = Encoding.UTF8.GetBytes(key),
|
||||
Mode = System.Security.Cryptography.CipherMode.ECB,
|
||||
Padding = System.Security.Cryptography.PaddingMode.PKCS7
|
||||
};
|
||||
|
||||
var cTransform = rm.CreateDecryptor();
|
||||
var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
|
||||
|
||||
return resultArray;
|
||||
}
|
||||
|
||||
static decimal unitT = new decimal(1000000000000L);
|
||||
static decimal unitQ = new decimal(1000000000000000L);
|
||||
|
||||
public static string GetNumStringFloorInt(ulong coin_num)
|
||||
{
|
||||
decimal v = 0m;
|
||||
var suffix = string.Empty;
|
||||
|
||||
if (coin_num < 1000)
|
||||
{
|
||||
v = coin_num;
|
||||
}
|
||||
else if (coin_num >= 1000 && coin_num < 1000000)
|
||||
{
|
||||
v = coin_num / 1000m;
|
||||
suffix = "K";
|
||||
}
|
||||
else if (coin_num >= 1000000 && coin_num < 1000000000)
|
||||
{
|
||||
v = coin_num / 1000000m;
|
||||
suffix = "M";
|
||||
}
|
||||
else if (coin_num >= 1000000000 && coin_num < 1000000000000)
|
||||
{
|
||||
v = coin_num / 1000000000m;
|
||||
suffix = "B";
|
||||
}
|
||||
else if (coin_num >= 1000000000000 && coin_num < 1000000000000000)
|
||||
{
|
||||
v = coin_num / unitT;
|
||||
suffix = "T";
|
||||
}
|
||||
else if (coin_num >= 1000000000000000)
|
||||
{
|
||||
v = coin_num / unitQ;
|
||||
suffix = "Q";
|
||||
}
|
||||
|
||||
var floor_v = decimal.Truncate(v);
|
||||
var num_str = $"{floor_v:0}{suffix}";
|
||||
|
||||
return num_str;
|
||||
}
|
||||
|
||||
public static string GetNumString(ulong coin_num)
|
||||
{
|
||||
decimal v = 0m;
|
||||
var suffix = string.Empty;
|
||||
|
||||
if (coin_num < 1000)
|
||||
{
|
||||
v = coin_num;
|
||||
}
|
||||
else if (coin_num >= 1000 && coin_num < 1000000)
|
||||
{
|
||||
v = coin_num / 1000m;
|
||||
suffix = "K";
|
||||
}
|
||||
else if (coin_num >= 1000000 && coin_num < 1000000000)
|
||||
{
|
||||
v = coin_num / 1000000m;
|
||||
suffix = "M";
|
||||
}
|
||||
else if (coin_num >= 1000000000 && coin_num < 1000000000000)
|
||||
{
|
||||
v = coin_num / 1000000000m;
|
||||
suffix = "B";
|
||||
}
|
||||
else if (coin_num >= 1000000000000 && coin_num < 1000000000000000)
|
||||
{
|
||||
v = coin_num / unitT;
|
||||
suffix = "T";
|
||||
}
|
||||
else if (coin_num >= 1000000000000000)
|
||||
{
|
||||
v = coin_num / unitQ;
|
||||
suffix = "Q";
|
||||
}
|
||||
|
||||
var truncate_v = decimal.Truncate(v * 10) / 10;
|
||||
var num_str = $"{truncate_v:0.#}{suffix}";
|
||||
|
||||
return num_str;
|
||||
}
|
||||
|
||||
// public static string GetPayCountStr(uint price)
|
||||
// {
|
||||
// double pricereal = (double)((double)price / 100f);
|
||||
// return pricereal.ToString("N");
|
||||
// }
|
||||
|
||||
static readonly string[] suffixes = { "B", "KB", "MB", "GB", "TB", "PB" };
|
||||
|
||||
public static string GetSizeString(Int64 bytes)
|
||||
{
|
||||
int counter = 0;
|
||||
decimal number = (decimal)bytes;
|
||||
while (Math.Round(number / 1024) >= 1)
|
||||
{
|
||||
number /= 1024;
|
||||
counter++;
|
||||
}
|
||||
|
||||
return string.Format("{0:n1}{1}", number, suffixes[counter]);
|
||||
}
|
||||
|
||||
public static RectTransform SetParent(Transform child, Transform parent)
|
||||
{
|
||||
RectTransform childrect = child.transform.GetComponent<RectTransform>();
|
||||
RectTransform _parent = parent.transform.GetComponent<RectTransform>();
|
||||
childrect.SetParent(_parent);
|
||||
childrect.localScale = Vector3.one;
|
||||
childrect.anchoredPosition = Vector2.zero;
|
||||
return childrect;
|
||||
}
|
||||
|
||||
//public static void SetRendererGray(SpriteRenderer rend)
|
||||
//{
|
||||
//Material mat = AssetManager.LoadAsset<Material>("ImageGrayMat");
|
||||
|
||||
//if (mat != null)
|
||||
//{
|
||||
//rend.material = mat;
|
||||
//}
|
||||
//}
|
||||
|
||||
public static int TryParseInt(string data_string, int default_value = 0)
|
||||
{
|
||||
int set_data = default_value;
|
||||
|
||||
if (int.TryParse(data_string, out int parsed_value))
|
||||
{
|
||||
set_data = parsed_value;
|
||||
}
|
||||
|
||||
return set_data;
|
||||
}
|
||||
|
||||
public static ulong TryParseUlong(string data_string, ulong default_value = 0)
|
||||
{
|
||||
ulong set_data = default_value;
|
||||
|
||||
if (ulong.TryParse(data_string, out ulong parsed_value))
|
||||
{
|
||||
set_data = parsed_value;
|
||||
}
|
||||
|
||||
return set_data;
|
||||
}
|
||||
|
||||
public static DateTime TryParseDateTime(string data_string, DateTime default_value)
|
||||
{
|
||||
DateTime set_data = default_value;
|
||||
|
||||
if (DateTime.TryParse(data_string, out DateTime parsed_value))
|
||||
{
|
||||
set_data = parsed_value;
|
||||
}
|
||||
|
||||
return set_data;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR && EDITOR_GAMEVIEW_CHANGE_ENABLE
|
||||
static ScreenType currentGameViewType = ScreenType.INVALID;
|
||||
#endif
|
||||
|
||||
public static void ChangeEditorGameView(ScreenType game_view_type)
|
||||
{
|
||||
#if UNITY_EDITOR && EDITOR_GAMEVIEW_CHANGE_ENABLE
|
||||
if (currentGameViewType == game_view_type) return;
|
||||
|
||||
var is_auto_change_gameview = EditorPrefs.GetBool("AutoChangeGameView", false);
|
||||
|
||||
if (is_auto_change_gameview)
|
||||
{
|
||||
var windows = (EditorWindow[])Resources.FindObjectsOfTypeAll(typeof(EditorWindow));
|
||||
EditorWindow gameview_landscape = null;
|
||||
EditorWindow gameview_portrait = null;
|
||||
EditorWindow ab_buildview = null;
|
||||
EditorWindow inspector_window = null;
|
||||
EditorWindow jconsole_window = null;
|
||||
int num_gameview = 0;
|
||||
|
||||
foreach (var window in windows)
|
||||
{
|
||||
if (window == null) continue;
|
||||
|
||||
if (window.GetType().FullName == "UnityEditor.GameView")
|
||||
{
|
||||
var gameview_type = GameViewUtils.GetGameViewType(window);
|
||||
|
||||
if (gameview_type == ScreenType.LANDSCAPE)
|
||||
{
|
||||
gameview_landscape = window;
|
||||
}
|
||||
else
|
||||
{
|
||||
gameview_portrait = window;
|
||||
}
|
||||
|
||||
num_gameview++;
|
||||
}
|
||||
else if (window.titleContent.text == "Inspector")
|
||||
{
|
||||
inspector_window = window;
|
||||
}
|
||||
else if (window.titleContent.text == "AB打包窗口")
|
||||
{
|
||||
ab_buildview = window;
|
||||
}
|
||||
else if (window.titleContent.text == "JConsole")
|
||||
{
|
||||
jconsole_window = window;
|
||||
}
|
||||
}
|
||||
|
||||
if (game_view_type == ScreenType.PORTRAIT)
|
||||
{
|
||||
if (num_gameview == 1)
|
||||
{
|
||||
GameViewUtils.SetSize(5);
|
||||
}
|
||||
else if (num_gameview == 2)
|
||||
{
|
||||
if (ab_buildview != null)
|
||||
{
|
||||
ab_buildview.Focus();
|
||||
}
|
||||
|
||||
if (gameview_portrait != null)
|
||||
{
|
||||
gameview_portrait.Focus();
|
||||
}
|
||||
|
||||
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num_gameview == 1)
|
||||
{
|
||||
GameViewUtils.SetSize(6);
|
||||
}
|
||||
else if (num_gameview == 2)
|
||||
{
|
||||
if (jconsole_window != null)
|
||||
{
|
||||
jconsole_window.Focus();
|
||||
}
|
||||
else if (inspector_window != null)
|
||||
{
|
||||
inspector_window.Focus();
|
||||
}
|
||||
|
||||
if (gameview_landscape != null)
|
||||
{
|
||||
gameview_landscape.Focus();
|
||||
}
|
||||
|
||||
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var windows = (EditorWindow[])Resources.FindObjectsOfTypeAll(typeof(EditorWindow));
|
||||
foreach (var window in windows)
|
||||
{
|
||||
if (window != null && window.GetType().FullName == "UnityEditor.GameView")
|
||||
{
|
||||
if (!window.hasFocus)
|
||||
{
|
||||
window.Focus();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
|
||||
}
|
||||
|
||||
currentGameViewType = game_view_type;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/Scripts/Core/GlobalUtils.cs.meta
Normal file
11
Assets/Scripts/Core/GlobalUtils.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3472c8c4e5f231c4084dbb54174de30e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
11
Assets/Scripts/Core/OutPlayVibration.cs
Normal file
11
Assets/Scripts/Core/OutPlayVibration.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using asap.core;
|
||||
using UnityEngine;
|
||||
|
||||
public class OutPlayVibration : MonoBehaviour
|
||||
{
|
||||
public HapticTypes hapticTypes;
|
||||
private void OnEnable()
|
||||
{
|
||||
GContext.Publish(new VibrationData(hapticTypes));
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Core/OutPlayVibration.cs.meta
Normal file
11
Assets/Scripts/Core/OutPlayVibration.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30d578e4d3eaa404895ab4710bfb96fe
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
271
Assets/Scripts/Core/PlayFabMgr.cs
Normal file
271
Assets/Scripts/Core/PlayFabMgr.cs
Normal file
@@ -0,0 +1,271 @@
|
||||
using asap.core;
|
||||
using PlayFab;
|
||||
using PlayFab.ClientModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayFabMgr : MonoBehaviour
|
||||
{
|
||||
const int USER_DATA_UPDATE_INTERVAL = 40;
|
||||
const int Buffer_Count = 5;
|
||||
const string Last_Update_Time_Key_Prefix = "LastUpdateTime";
|
||||
const string Local_Data_Key_prefix = "LocalData";
|
||||
private string Last_Update_Time_Key;
|
||||
private string Local_Data_Key;
|
||||
|
||||
private LinkedList<Dictionary<string, string>> dataBuffer;
|
||||
private Dictionary<string, string> swapData;
|
||||
private Dictionary<string, long> lastUpdateTime;
|
||||
private Dictionary<string, string> localData;
|
||||
|
||||
private CancellationTokenSource tokenSource;
|
||||
|
||||
static PlayFabMgr _instance = null;
|
||||
|
||||
public static PlayFabMgr Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
GameDebug.LogError("PlayFabMgr Instance doesn't exist yet!");
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<string, string> CompareDatas(Dictionary<string, UserDataRecord> remoteDatas, string userId)
|
||||
{
|
||||
Last_Update_Time_Key = $"{Last_Update_Time_Key_Prefix}_{userId}";
|
||||
Local_Data_Key = $"{Local_Data_Key_prefix}_{userId}";
|
||||
var lastUpdateTimeStr = PlayerPrefs.GetString(Last_Update_Time_Key, string.Empty);
|
||||
var now = ZZTimeHelper.UtcNow().Ticks;
|
||||
localData = new Dictionary<string, string>();
|
||||
lastUpdateTime = new Dictionary<string, long>();
|
||||
|
||||
if (string.IsNullOrEmpty(lastUpdateTimeStr))
|
||||
{
|
||||
if (remoteDatas != null && remoteDatas.Count > 0)
|
||||
{
|
||||
lastUpdateTime = remoteDatas.ToDictionary(x => x.Key, x => x.Value.LastUpdated.Ticks);
|
||||
localData = remoteDatas.ToDictionary(x => x.Key, x => x.Value.Value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var tempLastUpdateTime = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, long>>(lastUpdateTimeStr);
|
||||
var localDataStr = PlayerPrefs.GetString(Local_Data_Key);
|
||||
var tempLocalData = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(localDataStr);
|
||||
var allKeys = tempLocalData.Keys.Concat(remoteDatas.Keys).Distinct();
|
||||
foreach (var key in allKeys)
|
||||
{
|
||||
var localValue = tempLocalData.ContainsKey(key) ? tempLocalData[key] : null;
|
||||
var remoteValue = remoteDatas.ContainsKey(key) ? remoteDatas[key].Value : null;
|
||||
var localTime = tempLastUpdateTime.ContainsKey(key) ? tempLastUpdateTime[key] : 0;
|
||||
var remoteTime = remoteDatas.ContainsKey(key) ? remoteDatas[key].LastUpdated.Ticks : 0;
|
||||
|
||||
if (localValue == null)
|
||||
{
|
||||
localData[key] = remoteValue;
|
||||
lastUpdateTime[key] = remoteTime;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (remoteValue == null)
|
||||
{
|
||||
UpdateUserDataValue(key, localValue);
|
||||
lastUpdateTime[key] = now;
|
||||
localData[key] = localValue;
|
||||
continue;
|
||||
}
|
||||
|
||||
var timeDelta = localTime - remoteTime;
|
||||
if (Math.Abs(timeDelta) > TimeSpan.TicksPerSecond * 60)
|
||||
{
|
||||
if (localTime > remoteTime)
|
||||
{
|
||||
UpdateUserDataValue(key, localValue);
|
||||
lastUpdateTime[key] = now;
|
||||
localData[key] = localValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastUpdateTime[key] = remoteTime;
|
||||
localData[key] = remoteValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lastUpdateTime[key] = localTime;
|
||||
localData[key] = localValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlayerPrefs.SetString(Last_Update_Time_Key, LitJson.JsonMapper.ToJson(lastUpdateTime));
|
||||
PlayerPrefs.SetString(Local_Data_Key, LitJson.JsonMapper.ToJson(localData));
|
||||
return localData;
|
||||
}
|
||||
|
||||
void Awake()
|
||||
{
|
||||
_instance = this;
|
||||
InitBuffer();
|
||||
tokenSource = new CancellationTokenSource();
|
||||
UpdateUserDataValue(tokenSource.Token);
|
||||
}
|
||||
|
||||
void InitBuffer()
|
||||
{
|
||||
dataBuffer = new LinkedList<Dictionary<string, string>>();
|
||||
for (int i = 0; i < Buffer_Count; i++)
|
||||
{
|
||||
dataBuffer.AddLast(new Dictionary<string, string>());
|
||||
}
|
||||
swapData = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
void OnApplicationPause(bool is_pause)
|
||||
{
|
||||
if (is_pause)
|
||||
{
|
||||
tokenSource.Cancel();
|
||||
tokenSource = null;
|
||||
SyncData();
|
||||
}
|
||||
else
|
||||
{
|
||||
tokenSource = new CancellationTokenSource();
|
||||
UpdateUserDataValue(tokenSource.Token);
|
||||
}
|
||||
}
|
||||
|
||||
void OnApplicationQuit()
|
||||
{
|
||||
tokenSource.Cancel();
|
||||
tokenSource = null;
|
||||
SyncData();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
tokenSource?.Cancel();
|
||||
tokenSource = null;
|
||||
SyncData();
|
||||
}
|
||||
|
||||
private async void UpdateUserDataValue(CancellationToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
SyncData();
|
||||
await Task.Delay(USER_DATA_UPDATE_INTERVAL * 1000);
|
||||
}
|
||||
}
|
||||
catch (System.Exception) { }
|
||||
}
|
||||
|
||||
public void UpdateUserDataValue(string key, string data, bool remoteStore = true)
|
||||
{
|
||||
if(remoteStore)
|
||||
{
|
||||
var cbuff = dataBuffer.First;
|
||||
while (cbuff != null)
|
||||
{
|
||||
var datas = cbuff.Value;
|
||||
if (!datas.ContainsKey(key) && datas.Count >= 10)
|
||||
{
|
||||
cbuff = cbuff.Next;
|
||||
continue;
|
||||
}
|
||||
cbuff.Value[key] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
localData[key] = data;
|
||||
lastUpdateTime[key] = ZZTimeHelper.UtcNow().Ticks;
|
||||
|
||||
PlayerPrefs.SetString(Last_Update_Time_Key, LitJson.JsonMapper.ToJson(lastUpdateTime));
|
||||
PlayerPrefs.SetString(Local_Data_Key, LitJson.JsonMapper.ToJson(localData));
|
||||
}
|
||||
/// <summary>
|
||||
/// 没有数据返回 null 一定一定一定判空!!!
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public string GetLocalData(string key)
|
||||
{
|
||||
if (localData.ContainsKey(key))
|
||||
{
|
||||
return localData[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void SyncData()
|
||||
{
|
||||
var buf = dataBuffer.First;
|
||||
if (buf.Value.Count == 0)
|
||||
return;
|
||||
|
||||
var datas = buf.Value;
|
||||
swapData.Clear();
|
||||
buf.Value = swapData;
|
||||
swapData = datas;
|
||||
|
||||
dataBuffer.RemoveFirst();
|
||||
dataBuffer.AddLast(buf);
|
||||
|
||||
var request = new UpdateUserDataRequest()
|
||||
{
|
||||
Data = swapData,
|
||||
Permission = UserDataPermission.Public
|
||||
};
|
||||
|
||||
PlayFabClientAPI.UpdateUserData(request, null, UpdateFaild);
|
||||
}
|
||||
|
||||
private void UpdateFaild(PlayFabError error)
|
||||
{
|
||||
GameDebug.LogError("[PlayFabMgr]UpdateUserData Error: {0}", error.ToString());
|
||||
}
|
||||
|
||||
public async Task<bool> SyncDataImmidiate(string key, string data)
|
||||
{
|
||||
foreach(var buff in dataBuffer)
|
||||
{
|
||||
if(buff.ContainsKey(key))
|
||||
{
|
||||
buff.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
var taskSource = new TaskCompletionSource<bool>();
|
||||
|
||||
var request = new UpdateUserDataRequest()
|
||||
{
|
||||
Data = new Dictionary<string, string>() { { key, data } },
|
||||
Permission = UserDataPermission.Public
|
||||
};
|
||||
|
||||
PlayFabClientAPI.UpdateUserData(request,
|
||||
(r) => { taskSource.SetResult(true); },
|
||||
(e) => {
|
||||
taskSource.SetResult(false);
|
||||
UnityEngine.Debug.LogError($"[PlayFabMgr]UpdateUserData Error: {e.ToString()}");
|
||||
}
|
||||
);
|
||||
return await taskSource.Task;
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Core/PlayFabMgr.cs.meta
Normal file
11
Assets/Scripts/Core/PlayFabMgr.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee122ad5cb7a1f142a4c150b403102bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
610
Assets/Scripts/Core/SoundMgr.cs
Normal file
610
Assets/Scripts/Core/SoundMgr.cs
Normal file
@@ -0,0 +1,610 @@
|
||||
using UnityEngine;
|
||||
using asap.core;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using System.Collections.Generic;
|
||||
using UniRx;
|
||||
using GameCore;
|
||||
using cfg;
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
using game;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using System.Linq;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
|
||||
public struct ChangeRodDataEvent
|
||||
{
|
||||
public ChangeRodDataEvent(int rodId)
|
||||
{
|
||||
RodId = rodId;
|
||||
}
|
||||
public int RodId;
|
||||
}
|
||||
public interface IEventData
|
||||
{
|
||||
public SoundType audioType { set; get; }
|
||||
public string audioNameStr { set; get; }
|
||||
public float time { set; get; }
|
||||
}
|
||||
public class EventFishingSound : IEventData
|
||||
{
|
||||
public EventFishingSound(SoundType audioName, float time = 0, bool loop = false)
|
||||
{
|
||||
this.audioType = audioName;
|
||||
this.audioNameStr = audioName.ToString();
|
||||
this.time = time;
|
||||
this.loop = loop;
|
||||
}
|
||||
public EventFishingSound(string audioName, float time = 0)
|
||||
{
|
||||
this.audioType = SoundType.Fishing;
|
||||
this.audioNameStr = audioName;
|
||||
this.time = time;
|
||||
}
|
||||
public Sound Sound { set; get; }
|
||||
public SoundType audioType { set; get; }
|
||||
public string audioNameStr { set; get; }
|
||||
public float time { set; get; }
|
||||
public bool loop { set; get; }
|
||||
}
|
||||
public class EventUISound : IEventData
|
||||
{
|
||||
public EventUISound(SoundType audioName, float time = 0)
|
||||
{
|
||||
this.audioType = audioName;
|
||||
this.audioNameStr = audioName.ToString();
|
||||
this.time = time;
|
||||
}
|
||||
public EventUISound(string audioName, float time = 0)
|
||||
{
|
||||
this.audioType = SoundType.UI;
|
||||
this.audioNameStr = audioName;
|
||||
this.time = time;
|
||||
}
|
||||
public Sound Sound { set; get; }
|
||||
|
||||
public SoundType audioType { set; get; }
|
||||
public string audioNameStr { set; get; }
|
||||
public float time { set; get; }
|
||||
}
|
||||
|
||||
public class EventBGMSound : IEventData
|
||||
{
|
||||
public EventBGMSound(string audioName, float time = 0)
|
||||
{
|
||||
this.audioType = SoundType.BGM;
|
||||
this.audioNameStr = audioName;
|
||||
this.time = time;
|
||||
}
|
||||
public SoundType audioType { set; get; }
|
||||
public string audioNameStr { set; get; }
|
||||
public float time { set; get; }
|
||||
}
|
||||
public class FadeOutEvent
|
||||
{
|
||||
public FadeOutEvent(Sound sound, float timer = 0.5f)
|
||||
{
|
||||
this.sound = sound;
|
||||
this.timer = timer;
|
||||
}
|
||||
public Sound sound { set; get; }
|
||||
public float timer { set; get; }
|
||||
}
|
||||
public struct SoundMuteEvent
|
||||
{
|
||||
public SoundMuteEvent(int muteType)
|
||||
{
|
||||
this.muteType = muteType;
|
||||
}
|
||||
public int muteType;
|
||||
|
||||
}
|
||||
public class AssetReferenceAudioClip
|
||||
{
|
||||
public AssetReferenceAudioClip(AssetReferenceT<AudioClip> assetReference, bool isOutDisable = false, SoundMainType mainType = SoundMainType.UI, float time = 0)
|
||||
{
|
||||
this.assetReference = assetReference;
|
||||
this.time = time;
|
||||
this.mainType = mainType;
|
||||
this.isOutDisable = isOutDisable;
|
||||
}
|
||||
public AssetReferenceT<AudioClip> assetReference;
|
||||
public Sound Sound { set; get; }
|
||||
public float time { set; get; }
|
||||
public SoundMainType mainType { set; get; }
|
||||
public bool isOutDisable = false;
|
||||
}
|
||||
public class AssetReferenceAudioVoiceClip
|
||||
{
|
||||
public AssetReferenceAudioVoiceClip(AssetReferenceT<AudioClip> assetReference)
|
||||
{
|
||||
this.assetReference = assetReference;
|
||||
}
|
||||
public AssetReferenceT<AudioClip> assetReference;
|
||||
public Sound Sound { set; get; }
|
||||
}
|
||||
public class OnSoundStateEvent
|
||||
{
|
||||
public OnSoundStateEvent(int type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
public int type;
|
||||
}
|
||||
public class SoundMgr
|
||||
{
|
||||
[Inject]
|
||||
public ISoundService soundService { set; get; }
|
||||
public Tables _tables { set; get; }
|
||||
string[] residentFish =
|
||||
{ SoundType.audio_fishing_waiting.ToString(),
|
||||
SoundType.audio_fishing_waiting_fishgathering.ToString(),
|
||||
"audio_fishing_drawing_hpevent_01", "audio_fishing_drawing_hpevent_02","audio_fishing_drawing_hpevent_03","audio_fishing_drawing_hpevent_04","audio_fishing_drawing_hpevent_05",
|
||||
SoundType.audio_fishing_welldone.ToString(),
|
||||
SoundType.audio_fishing_switchrod.ToString(),
|
||||
SoundType.audio_ui_targetcollect_collecting.ToString(),
|
||||
SoundType.audio_ui_targetcollect_fly.ToString(),
|
||||
"audio_fishing_pulling_fishflapping_01","audio_fishing_pulling_fishflapping_02","audio_fishing_pulling_fishflapping_03",
|
||||
SoundType.audio_ui_fishingmap_btn_levelup.ToString(),
|
||||
SoundType.audio_ui_fishingmap_fishpointfly.ToString(),
|
||||
SoundType.audio_fishing_dash.ToString(),
|
||||
SoundType.audio_fishing_fail_forcetoobig.ToString(),
|
||||
SoundType.audio_fishing_fail_forcetoosmall.ToString(),
|
||||
"audio_fishing_piercing01","audio_fishing_piercing02","audio_fishing_piercing03",
|
||||
};
|
||||
Dictionary<string, AudioClip> residentClip;
|
||||
Sound BGM_Sound;
|
||||
AudioClip BGM_Clip;
|
||||
RodSkinData rodData;
|
||||
OnSoundStateEvent onSoundState = new OnSoundStateEvent(0);
|
||||
string BGMName;
|
||||
protected CompositeDisposable disposables;
|
||||
public async Task Init(System.Action<float> progress)
|
||||
{
|
||||
//playerData = GContext.container.Resolve<PlayerData>();
|
||||
_tables = GContext.container.Resolve<cfg.Tables>();
|
||||
//var service = (SoundService)soundService;
|
||||
await soundService.InitAsync();
|
||||
|
||||
var opMap = new Dictionary<string, AsyncOperationHandle<AudioClip>>();
|
||||
|
||||
foreach (var addr in residentFish)
|
||||
{
|
||||
opMap[addr] = Addressables.LoadAssetAsync<AudioClip>(addr);
|
||||
}
|
||||
|
||||
var tasks = opMap.Values.Select(_ => _.Task);
|
||||
var total = (float)tasks.Count();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var completed = tasks.Count(_ => _.IsCompleted);
|
||||
if (completed == total)
|
||||
{
|
||||
progress.Invoke(1f);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
progress.Invoke(completed / total);
|
||||
}
|
||||
await Awaiters.NextFrame;
|
||||
}
|
||||
|
||||
residentClip = opMap.ToDictionary(_ => _.Key, _ => _.Value.Result);
|
||||
disposables = new CompositeDisposable();
|
||||
GContext.OnEvent<EventUISound>().Subscribe(PlaySound).AddTo(disposables);
|
||||
GContext.OnEvent<EventFishingSound>().Subscribe(PlayFishingSound).AddTo(disposables);
|
||||
GContext.OnEvent<EventBGMSound>().Subscribe(PlayMusic).AddTo(disposables);
|
||||
GContext.OnEvent<FadeOutEvent>().Subscribe(FadeOutEvent).AddTo(disposables);
|
||||
GContext.OnEvent<AssetReferenceAudioClip>().Subscribe(PlaySoundByReference).AddTo(disposables);
|
||||
GContext.OnEvent<AssetReferenceAudioVoiceClip>().Subscribe(PlayVoiceSoundByReference).AddTo(disposables);
|
||||
|
||||
GContext.OnEvent<ChangeRodDataEvent>().Subscribe(OnChangeRodData).AddTo(disposables);
|
||||
GContext.OnEvent<SoundMuteEvent>().Subscribe(OnSoundMute).AddTo(disposables);
|
||||
GContext.OnEvent<OnSoundStateEvent>().Subscribe(OnSoundStateEvent).AddTo(disposables);
|
||||
soundService.BGMVol = GContext.container.Resolve<ISettingService>().Music ? 80 : 0;
|
||||
soundService.SFXVol = GContext.container.Resolve<ISettingService>().Sound ? 80 : 0;
|
||||
soundService.VoiceVol = GContext.container.Resolve<ISettingService>().Sound ? 80 : 0;
|
||||
}
|
||||
void OnSoundStateEvent(OnSoundStateEvent onSoundStateEvent)
|
||||
{
|
||||
onSoundState = onSoundStateEvent;
|
||||
SetSoundVolume(onSoundStateEvent.type);
|
||||
}
|
||||
void OnSoundMute(SoundMuteEvent soundMuteEvent)
|
||||
{
|
||||
if (soundMuteEvent.muteType == 0)
|
||||
{
|
||||
soundService.BGMVol = GContext.container.Resolve<ISettingService>().Music ? 80 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
soundService.VoiceVol = GContext.container.Resolve<ISettingService>().Sound ? 80 : 0;
|
||||
soundService.SFXVol = GContext.container.Resolve<ISettingService>().Sound ? 80 : 0;
|
||||
}
|
||||
}
|
||||
public async void OnChangeRodData(ChangeRodDataEvent changeRodDataEvent)
|
||||
{
|
||||
AudioClip audioClip;
|
||||
if (rodData != null)
|
||||
{
|
||||
if (residentClip.TryGetValue(rodData.ThrowingAudio, out audioClip))
|
||||
{
|
||||
Addressables.Release(audioClip);
|
||||
residentClip.Remove(rodData.ThrowingAudio);
|
||||
}
|
||||
if (residentClip.TryGetValue(rodData.ReelingAudio, out audioClip))
|
||||
{
|
||||
Addressables.Release(audioClip);
|
||||
residentClip.Remove(rodData.ReelingAudio);
|
||||
}
|
||||
if (residentClip.TryGetValue(rodData.LineAudio, out audioClip))
|
||||
{
|
||||
Addressables.Release(audioClip);
|
||||
residentClip.Remove(rodData.LineAudio);
|
||||
}
|
||||
if (residentClip.TryGetValue(rodData.ComboOutAudio, out audioClip))
|
||||
{
|
||||
Addressables.Release(audioClip);
|
||||
residentClip.Remove(rodData.ComboOutAudio);
|
||||
}
|
||||
if (residentClip.TryGetValue(rodData.ComboLoopAudio, out audioClip))
|
||||
{
|
||||
Addressables.Release(audioClip);
|
||||
residentClip.Remove(rodData.ComboLoopAudio);
|
||||
}
|
||||
if (residentClip.TryGetValue(rodData.ComboIntoAudio, out audioClip))
|
||||
{
|
||||
Addressables.Release(audioClip);
|
||||
residentClip.Remove(rodData.ComboIntoAudio);
|
||||
}
|
||||
}
|
||||
int skindID = GContext.container.Resolve<PlayerFishData>().GetRodSkin(changeRodDataEvent.RodId);
|
||||
rodData = _tables.TbRodSkinData.GetOrDefault(skindID);
|
||||
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.ThrowingAudio).Task;
|
||||
residentClip.Add(rodData.ThrowingAudio, audioClip);
|
||||
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.ReelingAudio).Task;
|
||||
residentClip.Add(rodData.ReelingAudio, audioClip);
|
||||
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.LineAudio).Task;
|
||||
residentClip.Add(rodData.LineAudio, audioClip);
|
||||
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.ComboOutAudio).Task;
|
||||
residentClip.Add(rodData.ComboOutAudio, audioClip);
|
||||
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.ComboLoopAudio).Task;
|
||||
residentClip.Add(rodData.ComboLoopAudio, audioClip);
|
||||
audioClip = await Addressables.LoadAssetAsync<AudioClip>(rodData.ComboIntoAudio).Task;
|
||||
residentClip.Add(rodData.ComboIntoAudio, audioClip);
|
||||
}
|
||||
public async void PlaySoundByReference(AssetReferenceAudioClip eventSound)
|
||||
{
|
||||
string audioName = eventSound.assetReference.AssetGUID;
|
||||
if (!residentClip.TryGetValue(audioName, out var audioClip) || audioClip == null)
|
||||
{
|
||||
if (audioClip == null)
|
||||
{
|
||||
residentClip.Remove(audioName);
|
||||
}
|
||||
var audioClipL = await Addressables.LoadAssetAsync<AudioClip>(eventSound.assetReference).Task;//.LoadAssetAsync<AudioClip>().Task;
|
||||
if (disposables == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (residentClip.TryGetValue(audioName, out audioClip))
|
||||
{
|
||||
Addressables.Release(audioClipL);
|
||||
}
|
||||
else
|
||||
{
|
||||
residentClip.Add(audioName, audioClipL);
|
||||
audioClip = audioClipL;
|
||||
}
|
||||
}
|
||||
if (audioClip == null)
|
||||
{
|
||||
soundService.ReturnSound(eventSound.Sound);
|
||||
eventSound.Sound = null;
|
||||
return;
|
||||
}
|
||||
|
||||
SoundMainType soundMainType = eventSound.mainType;
|
||||
Sound sound;
|
||||
switch (soundMainType)
|
||||
{
|
||||
case SoundMainType.BGM:
|
||||
await PlayBGM(audioClip, eventSound.time);
|
||||
residentClip.Remove(audioName);
|
||||
if (disposables == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
case SoundMainType.Fishing:
|
||||
sound = soundService.GetNewFishingSound(audioClip, time: eventSound.time);
|
||||
sound.soundMainType = SoundMainType.Fishing;
|
||||
break;
|
||||
case SoundMainType.Voice:
|
||||
SetSoundVolume(2);
|
||||
sound = soundService.GetNewVoiceSound(audioClip);
|
||||
sound.soundMainType = SoundMainType.Voice;
|
||||
break;
|
||||
case SoundMainType.UILoop:
|
||||
sound = soundService.GetNewUISound(audioClip, loop: true, time: eventSound.time);
|
||||
sound.soundMainType = SoundMainType.UI;
|
||||
break;
|
||||
case SoundMainType.UI:
|
||||
default:
|
||||
sound = soundService.GetNewUISound(audioClip, time: eventSound.time);
|
||||
sound.soundMainType = SoundMainType.UI;
|
||||
break;
|
||||
}
|
||||
if (sound != null)
|
||||
{
|
||||
sound.audioSource.Play();
|
||||
eventSound.Sound = sound;
|
||||
await Awaiters.Seconds(audioClip.length);
|
||||
if (eventSound.Sound.soundMainType == SoundMainType.Voice)
|
||||
{
|
||||
SetSoundVolume(onSoundState.type);
|
||||
}
|
||||
if (soundMainType == eventSound.Sound.soundMainType && !eventSound.isOutDisable)
|
||||
{
|
||||
soundService.ReturnSound(sound);
|
||||
eventSound.Sound = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
async void PlayVoiceSoundByReference(AssetReferenceAudioVoiceClip eventSound)
|
||||
{
|
||||
var audioClip = await Addressables.LoadAssetAsync<AudioClip>(eventSound.assetReference).Task; // eventSound.assetReference.LoadAssetAsync<AudioClip>().Task;
|
||||
|
||||
if (audioClip == null)
|
||||
{
|
||||
eventSound.Sound = null;
|
||||
return;
|
||||
}
|
||||
SetSoundVolume(2);
|
||||
var sound = soundService.GetNewVoiceSound(audioClip);
|
||||
sound.soundMainType = SoundMainType.Voice;
|
||||
sound.audioSource.Play();
|
||||
eventSound.Sound = sound;
|
||||
await Awaiters.Seconds(audioClip.length);
|
||||
if (eventSound.Sound.soundMainType == SoundMainType.Voice)
|
||||
{
|
||||
SetSoundVolume(onSoundState.type);
|
||||
soundService.ReturnSound(sound);
|
||||
}
|
||||
Addressables.Release(audioClip);
|
||||
eventSound.Sound = null;
|
||||
}
|
||||
/// <summary>
|
||||
/// 0默认 type==1 钓鱼 type==2 人声
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
void SetSoundVolume(int type)
|
||||
{
|
||||
if (GContext.container.Resolve<ISettingService>().Music)
|
||||
{
|
||||
soundService.BGMVol = type == 0 ? 80 : 72;
|
||||
}
|
||||
if (GContext.container.Resolve<ISettingService>().Sound)
|
||||
{
|
||||
soundService.SFXVol = type == 2 ? 70 : 80;
|
||||
}
|
||||
}
|
||||
public async void PlaySound(EventUISound eventSound)
|
||||
{
|
||||
string audioName = GetAudioName(eventSound);
|
||||
|
||||
if (!residentClip.TryGetValue(audioName, out var audioClip))
|
||||
{
|
||||
var audioClipL = await Addressables.LoadAssetAsync<AudioClip>(audioName).Task;
|
||||
if (residentClip.TryGetValue(audioName, out audioClip))
|
||||
{
|
||||
Addressables.Release(audioClipL);
|
||||
}
|
||||
else
|
||||
{
|
||||
residentClip.Add(audioName, audioClipL);
|
||||
audioClip = audioClipL;
|
||||
}
|
||||
}
|
||||
if (audioClip == null)
|
||||
{
|
||||
eventSound.Sound = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var sound = soundService.GetNewUISound(audioClip, time: eventSound.time);
|
||||
sound.soundMainType = SoundMainType.UI;
|
||||
sound.audioSource.Play();
|
||||
eventSound.Sound = sound;
|
||||
await Awaiters.Seconds(audioClip.length);
|
||||
if (SoundMainType.UI == eventSound.Sound.soundMainType)
|
||||
{
|
||||
soundService.ReturnSound(sound);
|
||||
}
|
||||
eventSound.Sound = null;
|
||||
}
|
||||
public async void PlayFishingSound(EventFishingSound eventSound)
|
||||
{
|
||||
string audioName = GetAudioName(eventSound);
|
||||
|
||||
if (!residentClip.TryGetValue(audioName, out var audioClip))
|
||||
{
|
||||
var audioClipL = await Addressables.LoadAssetAsync<AudioClip>(audioName).Task;
|
||||
if (residentClip.TryGetValue(audioName, out audioClip))
|
||||
{
|
||||
Addressables.Release(audioClipL);
|
||||
}
|
||||
else
|
||||
{
|
||||
residentClip.Add(audioName, audioClipL);
|
||||
audioClip = audioClipL;
|
||||
}
|
||||
}
|
||||
if (audioClip == null)
|
||||
{
|
||||
eventSound.Sound = null;
|
||||
return;
|
||||
}
|
||||
bool isLoop = eventSound.loop;
|
||||
//if (eventSound.audioType == SoundType.LineAudioReeling || eventSound.audioType == SoundType.ReelingAudioReeling)
|
||||
//{
|
||||
// isLoop = true;
|
||||
//}
|
||||
var sound = soundService.GetNewFishingSound(audioClip, loop: isLoop, time: eventSound.time);
|
||||
sound.soundMainType = SoundMainType.Fishing;
|
||||
sound.audioSource.Play();
|
||||
eventSound.Sound = sound;
|
||||
if (!isLoop)
|
||||
{
|
||||
await Awaiters.Seconds(audioClip.length);
|
||||
if (eventSound.Sound != null && SoundMainType.Fishing == eventSound.Sound.soundMainType)
|
||||
{
|
||||
soundService.ReturnSound(sound);
|
||||
}
|
||||
eventSound.Sound = null;
|
||||
}
|
||||
}
|
||||
public async void PlayMusic(EventBGMSound eventSound)
|
||||
{
|
||||
string audioName = GetAudioName(eventSound);
|
||||
if (BGMName == audioName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var audioClip = await Addressables.LoadAssetAsync<AudioClip>(audioName).Task;
|
||||
if (BGMName == audioName)
|
||||
{
|
||||
Addressables.Release(audioClip);
|
||||
return;
|
||||
}
|
||||
await PlayBGM(audioClip, eventSound.time);
|
||||
}
|
||||
async Task PlayBGM(AudioClip audioClip, float time = 0)
|
||||
{
|
||||
if (audioClip == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
BGMName = audioClip.name;
|
||||
|
||||
if (BGM_Clip != null)
|
||||
{
|
||||
AudioClip audioClip1 = BGM_Clip;
|
||||
BGM_Clip = null;
|
||||
Sound bgm_Sound = BGM_Sound;
|
||||
BGM_Sound = null;
|
||||
soundService.FadeOut(bgm_Sound, 0.5f);
|
||||
await Task.Delay(500);
|
||||
Addressables.Release(audioClip1);
|
||||
soundService.ReturnSound(bgm_Sound);
|
||||
}
|
||||
if (BGMName != audioClip.name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
BGM_Sound = soundService.GetNewBgmSound(audioClip, time: time);
|
||||
BGM_Sound.soundMainType = SoundMainType.BGM;
|
||||
BGM_Clip = audioClip;
|
||||
BGM_Sound.audioSource.Play();
|
||||
soundService.FadeIn(BGM_Sound, 0.5f);
|
||||
}
|
||||
public void SetBGM(AudioClip audioClip)
|
||||
{
|
||||
if (audioClip == BGM_Clip)
|
||||
return;
|
||||
if (BGM_Sound == null)
|
||||
{
|
||||
BGM_Sound = soundService.GetNewBgmSound(audioClip);
|
||||
}
|
||||
BGM_Sound.audioSource.clip = audioClip;
|
||||
BGM_Sound.soundMainType = SoundMainType.BGM;
|
||||
BGM_Clip = audioClip;
|
||||
BGM_Sound.audioSource.Play();
|
||||
}
|
||||
void FadeOutEvent(FadeOutEvent fadeOutEvent)
|
||||
{
|
||||
_ = FadeOutAsync(fadeOutEvent.sound, fadeOutEvent.timer);
|
||||
fadeOutEvent.sound = null;
|
||||
}
|
||||
async Task FadeOutAsync(Sound sound, float timer = 0.5f)
|
||||
{
|
||||
if (sound == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (sound.soundMainType == SoundMainType.Voice)
|
||||
{
|
||||
SetSoundVolume(onSoundState.type);
|
||||
}
|
||||
if (sound.soundMainType == SoundMainType.BGM)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
soundService.FadeOut(sound, timer);
|
||||
await Task.Delay((int)(timer * 1000));
|
||||
if (sound.soundMainType != SoundMainType.None)
|
||||
{
|
||||
soundService.ReturnSound(sound);
|
||||
}
|
||||
}
|
||||
|
||||
string GetAudioName(IEventData eventData)
|
||||
{
|
||||
PlayerData playerData = GContext.container.Resolve<PlayerData>();
|
||||
PlayerFishData playerFishData = GContext.container.Resolve<PlayerFishData>();
|
||||
int skindID = playerFishData.GetRodSkin(playerData.equipRodID);
|
||||
RodSkinData rodSkinData = _tables.TbRodSkinData.GetOrDefault(skindID);
|
||||
switch (eventData.audioType)
|
||||
{
|
||||
case SoundType.ThrowingAudio:
|
||||
return rodSkinData.ThrowingAudio;
|
||||
case SoundType.ReelingAudio:
|
||||
case SoundType.ReelingAudioReeling:
|
||||
return rodSkinData.ReelingAudio;
|
||||
case SoundType.LineAudioReeling:
|
||||
return rodSkinData.LineAudio;
|
||||
case SoundType.ComboOutAudio:
|
||||
return rodSkinData.ComboOutAudio;
|
||||
case SoundType.ComboLoopAudio:
|
||||
return rodSkinData.ComboLoopAudio;
|
||||
case SoundType.ComboIntoAudio:
|
||||
return rodSkinData.ComboIntoAudio;
|
||||
case SoundType.HPEvent:
|
||||
return "audio_fishing_drawing_hpevent_0" + Random.Range(1, 6);
|
||||
case SoundType.audio_fishing_piercing:
|
||||
return "audio_fishing_piercing0" + Random.Range(1, 4);
|
||||
case SoundType.audio_fishing_jumpout:
|
||||
return "audio_fishing_jumpout_0" + Random.Range(1, 4);
|
||||
case SoundType.audio_fishing_jumpinto:
|
||||
return "audio_fishing_jumpinto_0" + Random.Range(1, 4);
|
||||
case SoundType.BGM:
|
||||
case SoundType.Fishing:
|
||||
case SoundType.UI:
|
||||
default:
|
||||
return eventData.audioNameStr;
|
||||
}
|
||||
}
|
||||
public void Release()
|
||||
{
|
||||
disposables?.Dispose();
|
||||
disposables = null;
|
||||
residentClip.Clear();
|
||||
soundService.Release();
|
||||
foreach (var item in residentClip)
|
||||
{
|
||||
Addressables.Release(item.Value);
|
||||
}
|
||||
Addressables.Release(BGM_Clip);
|
||||
GameObject.Destroy(BGM_Sound.gameObject);
|
||||
BGM_Sound = null;
|
||||
BGM_Clip = null;
|
||||
BGMName = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Core/SoundMgr.cs.meta
Normal file
11
Assets/Scripts/Core/SoundMgr.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 909412df6a7eddf4c8882ebbe72fdcd6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
537
Assets/Scripts/Core/UnityTimer.cs
Normal file
537
Assets/Scripts/Core/UnityTimer.cs
Normal file
@@ -0,0 +1,537 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
/// <summary>
|
||||
/// Allows you to run events on a delay without the use of <see cref="Coroutine"/>s
|
||||
/// or <see cref="MonoBehaviour"/>s.
|
||||
///
|
||||
/// To create and start a Timer, use the <see cref="Register"/> method.
|
||||
/// </summary>
|
||||
namespace GameCore
|
||||
{
|
||||
public class Timer
|
||||
{
|
||||
#region Public Properties/Fields
|
||||
|
||||
/// <summary>
|
||||
/// How long the timer takes to complete from start to finish.
|
||||
/// </summary>
|
||||
public float duration { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the timer will run again after completion.
|
||||
/// </summary>
|
||||
public bool isLooped { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the timer completed running. This is false if the timer was canceled.
|
||||
/// </summary>
|
||||
public bool isCompleted { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the timer uses real-time or game-time. Real time is unaffected by changes to the timescale
|
||||
/// of the game(e.g. pausing, slow-mo), while game time is affected.
|
||||
/// </summary>
|
||||
public bool usesRealTime { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the timer is currently paused.
|
||||
/// </summary>
|
||||
public bool isPaused
|
||||
{
|
||||
get { return _timeElapsedBeforePause.HasValue; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not the timer was canceled.
|
||||
/// </summary>
|
||||
public bool isCancelled
|
||||
{
|
||||
get { return _timeElapsedBeforeCancel.HasValue; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get whether or not the timer has finished running for any reason.
|
||||
/// </summary>
|
||||
public bool isDone
|
||||
{
|
||||
get { return isCompleted || isCancelled || isOwnerDestroyed; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Static Methods
|
||||
public static void Create()
|
||||
{
|
||||
// create a manager object to update all the timers if one does not already exist.
|
||||
if (_manager != null)
|
||||
{
|
||||
Debug.LogError("[UnityTimer]Create: TimerManager already exist, ignore this call!");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[UnityTimer]Create");
|
||||
|
||||
var managerObject = new GameObject { name = nameof(TimerMgr) };
|
||||
Object.DontDestroyOnLoad(managerObject);
|
||||
_manager = managerObject.AddComponent<TimerMgr>();
|
||||
}
|
||||
|
||||
public static void Destroy()
|
||||
{
|
||||
Debug.Log($"[UnityTimer]Destroy");
|
||||
|
||||
if (_manager != null)
|
||||
{
|
||||
GameObject.Destroy(_manager.gameObject);
|
||||
_manager = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a new timer that should fire an event after a certain amount of time
|
||||
/// has elapsed.
|
||||
///
|
||||
/// Registered timers are destroyed when the scene changes.
|
||||
/// </summary>
|
||||
/// <param name="duration">The time to wait before the timer should fire, in seconds.</param>
|
||||
/// <param name="onComplete">An action to fire when the timer completes.</param>
|
||||
/// <param name="onUpdate">An action that should fire each time the timer is updated. Takes the amount
|
||||
/// of time passed in seconds since the start of the timer's current loop.</param>
|
||||
/// <param name="isLooped">Whether the timer should repeat after executing.</param>
|
||||
/// <param name="useRealTime">Whether the timer uses real-time(i.e. not affected by pauses,
|
||||
/// slow/fast motion) or game-time(will be affected by pauses and slow/fast-motion).</param>
|
||||
/// <param name="autoDestroyOwner">An object to attach this timer to. After the object is destroyed,
|
||||
/// the timer will expire and not execute. This allows you to avoid annoying <see cref="NullReferenceException"/>s
|
||||
/// by preventing the timer from running and accessing its parents' components
|
||||
/// after the parent has been destroyed.</param>
|
||||
/// <returns>A timer object that allows you to examine stats and stop/resume progress.</returns>
|
||||
public static Timer Register(float duration, Action onComplete, Action<float> onUpdate = null,
|
||||
bool isLooped = false, bool useRealTime = false, MonoBehaviour autoDestroyOwner = null)
|
||||
{
|
||||
if (_manager == null)
|
||||
{
|
||||
Debug.LogError("[UnityTimer]Register: TimerManager doesn't exist yet!");
|
||||
return null;
|
||||
}
|
||||
|
||||
Timer timer = new Timer(duration, onComplete, onUpdate, isLooped, useRealTime, autoDestroyOwner);
|
||||
_manager.RegisterTimer(timer);
|
||||
return timer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cancels a timer. The main benefit of this over the method on the instance is that you will not get
|
||||
/// a <see cref="NullReferenceException"/> if the timer is null.
|
||||
/// </summary>
|
||||
/// <param name="timer">The timer to cancel.</param>
|
||||
public static void Cancel(Timer timer)
|
||||
{
|
||||
timer?.Cancel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause a timer. The main benefit of this over the method on the instance is that you will not get
|
||||
/// a <see cref="NullReferenceException"/> if the timer is null.
|
||||
/// </summary>
|
||||
/// <param name="timer">The timer to pause.</param>
|
||||
public static void Pause(Timer timer)
|
||||
{
|
||||
timer?.Pause();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resume a timer. The main benefit of this over the method on the instance is that you will not get
|
||||
/// a <see cref="NullReferenceException"/> if the timer is null.
|
||||
/// </summary>
|
||||
/// <param name="timer">The timer to resume.</param>
|
||||
public static void Resume(Timer timer)
|
||||
{
|
||||
timer?.Resume();
|
||||
}
|
||||
|
||||
public static void CancelAllRegisteredTimers()
|
||||
{
|
||||
if (_manager != null)
|
||||
{
|
||||
_manager.CancelAllTimers();
|
||||
}
|
||||
|
||||
// if the manager doesn't exist, we don't have any registered timers yet, so don't
|
||||
// need to do anything in this case
|
||||
}
|
||||
|
||||
public static void PauseAllRegisteredTimers()
|
||||
{
|
||||
if (_manager != null)
|
||||
{
|
||||
_manager.PauseAllTimers();
|
||||
}
|
||||
|
||||
// if the manager doesn't exist, we don't have any registered timers yet, so don't
|
||||
// need to do anything in this case
|
||||
}
|
||||
|
||||
public static void ResumeAllRegisteredTimers()
|
||||
{
|
||||
if (_manager != null)
|
||||
{
|
||||
_manager.ResumeAllTimers();
|
||||
}
|
||||
|
||||
// if the manager doesn't exist, we don't have any registered timers yet, so don't
|
||||
// need to do anything in this case
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Stop a timer that is in-progress or paused. The timer's on completion callback will not be called.
|
||||
/// </summary>
|
||||
public void Cancel()
|
||||
{
|
||||
if (isDone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_timeElapsedBeforeCancel = GetTimeElapsed();
|
||||
_timeElapsedBeforePause = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause a running timer. A paused timer can be resumed from the same point it was paused.
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
if (isPaused || isDone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_timeElapsedBeforePause = GetTimeElapsed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Continue a paused timer. Does nothing if the timer has not been paused.
|
||||
/// </summary>
|
||||
public void Resume()
|
||||
{
|
||||
if (!isPaused || isDone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_timeElapsedBeforePause = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get how many seconds have elapsed since the start of this timer's current cycle.
|
||||
/// </summary>
|
||||
/// <returns>The number of seconds that have elapsed since the start of this timer's current cycle, i.e.
|
||||
/// the current loop if the timer is looped, or the start if it isn't.
|
||||
///
|
||||
/// If the timer has finished running, this is equal to the duration.
|
||||
///
|
||||
/// If the timer was cancelled/paused, this is equal to the number of seconds that passed between the timer
|
||||
/// starting and when it was cancelled/paused.</returns>
|
||||
public float GetTimeElapsed()
|
||||
{
|
||||
if (isCompleted || GetWorldTime() >= GetFireTime())
|
||||
{
|
||||
return duration;
|
||||
}
|
||||
|
||||
return _timeElapsedBeforeCancel ??
|
||||
_timeElapsedBeforePause ??
|
||||
GetWorldTime() - _startTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get how many seconds remain before the timer completes.
|
||||
/// </summary>
|
||||
/// <returns>The number of seconds that remain to be elapsed until the timer is completed. A timer
|
||||
/// is only elapsing time if it is not paused, cancelled, or completed. This will be equal to zero
|
||||
/// if the timer completed.</returns>
|
||||
public float GetTimeRemaining()
|
||||
{
|
||||
return duration - GetTimeElapsed();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get how much progress the timer has made from start to finish as a ratio.
|
||||
/// </summary>
|
||||
/// <returns>A value from 0 to 1 indicating how much of the timer's duration has been elapsed.</returns>
|
||||
public float GetRatioComplete()
|
||||
{
|
||||
return GetTimeElapsed() / duration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get how much progress the timer has left to make as a ratio.
|
||||
/// </summary>
|
||||
/// <returns>A value from 0 to 1 indicating how much of the timer's duration remains to be elapsed.</returns>
|
||||
public float GetRatioRemaining()
|
||||
{
|
||||
return GetTimeRemaining() / duration;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Static Properties/Fields
|
||||
|
||||
// responsible for updating all registered timers
|
||||
private static TimerMgr _manager;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Properties/Fields
|
||||
|
||||
private bool isOwnerDestroyed
|
||||
{
|
||||
get { return _hasAutoDestroyOwner && _autoDestroyOwner == null; }
|
||||
}
|
||||
|
||||
private readonly Action _onComplete;
|
||||
private readonly Action<float> _onUpdate;
|
||||
private float _startTime;
|
||||
private float _lastUpdateTime;
|
||||
|
||||
// for pausing, we push the start time forward by the amount of time that has passed.
|
||||
// this will mess with the amount of time that elapsed when we're cancelled or paused if we just
|
||||
// check the start time versus the current world time, so we need to cache the time that was elapsed
|
||||
// before we paused/cancelled
|
||||
private float? _timeElapsedBeforeCancel;
|
||||
private float? _timeElapsedBeforePause;
|
||||
|
||||
// after the auto destroy owner is destroyed, the timer will expire
|
||||
// this way you don't run into any annoying bugs with timers running and accessing objects
|
||||
// after they have been destroyed
|
||||
private readonly MonoBehaviour _autoDestroyOwner;
|
||||
private readonly bool _hasAutoDestroyOwner;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Constructor (use static Register method to create new timer)
|
||||
|
||||
private Timer(float duration, Action onComplete, Action<float> onUpdate,
|
||||
bool isLooped, bool usesRealTime, MonoBehaviour autoDestroyOwner)
|
||||
{
|
||||
this.duration = duration;
|
||||
_onComplete = onComplete;
|
||||
_onUpdate = onUpdate;
|
||||
|
||||
this.isLooped = isLooped;
|
||||
this.usesRealTime = usesRealTime;
|
||||
|
||||
_autoDestroyOwner = autoDestroyOwner;
|
||||
_hasAutoDestroyOwner = autoDestroyOwner != null;
|
||||
|
||||
_startTime = GetWorldTime();
|
||||
_lastUpdateTime = _startTime;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private float GetWorldTime()
|
||||
{
|
||||
return usesRealTime ? Time.realtimeSinceStartup : Time.time;
|
||||
}
|
||||
|
||||
private float GetFireTime()
|
||||
{
|
||||
return _startTime + duration;
|
||||
}
|
||||
|
||||
private float GetTimeDelta()
|
||||
{
|
||||
return GetWorldTime() - _lastUpdateTime;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (isDone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPaused)
|
||||
{
|
||||
_startTime += GetTimeDelta();
|
||||
_lastUpdateTime = GetWorldTime();
|
||||
return;
|
||||
}
|
||||
|
||||
_lastUpdateTime = GetWorldTime();
|
||||
|
||||
try
|
||||
{
|
||||
_onUpdate?.Invoke(GetTimeElapsed());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[Timer]Update: onUpdate error! {ex.Message}");
|
||||
}
|
||||
|
||||
if (GetWorldTime() >= GetFireTime())
|
||||
{
|
||||
try
|
||||
{
|
||||
_onComplete?.Invoke();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[Timer]Update: onComplete error! {ex.Message}");
|
||||
}
|
||||
|
||||
if (isLooped)
|
||||
{
|
||||
_startTime = GetWorldTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
isCompleted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Manager Class (implementation detail, spawned automatically and updates all registered timers)
|
||||
|
||||
/// <summary>
|
||||
/// Manages updating all the <see cref="Timer"/>s that are running in the application.
|
||||
/// This will be instantiated the first time you create a timer -- you do not need to add it into the
|
||||
/// scene manually.
|
||||
/// </summary>
|
||||
private class TimerMgr : MonoBehaviour
|
||||
{
|
||||
public int TimerCount { get; private set; }
|
||||
|
||||
private ulong _timerID;
|
||||
private Dictionary<ulong, Timer> _timers = new Dictionary<ulong, Timer>();
|
||||
// buffer adding timers so we don't edit a collection during iteration
|
||||
private List<Timer> _timersToAdd = new List<Timer>();
|
||||
// buffer removing timers
|
||||
private List<ulong> _timersToRemove = new List<ulong>();
|
||||
|
||||
public void RegisterTimer(Timer timer)
|
||||
{
|
||||
_timersToAdd.Add(timer);
|
||||
Debug.Log($"[TimerMgr]RegisterTimer: {TimerCount + _timersToAdd.Count} timers in total");
|
||||
}
|
||||
|
||||
public void CancelAllTimers()
|
||||
{
|
||||
Debug.Log($"[TimerMgr]CancelAllTimers");
|
||||
|
||||
var etor = _timers.GetEnumerator();
|
||||
while (etor.MoveNext())
|
||||
{
|
||||
var timer = etor.Current.Value;
|
||||
|
||||
timer.Cancel();
|
||||
}
|
||||
|
||||
_timers.Clear();
|
||||
_timersToAdd.Clear();
|
||||
TimerCount = 0;
|
||||
}
|
||||
|
||||
public void PauseAllTimers()
|
||||
{
|
||||
Debug.Log($"[TimerMgr]PauseAllTimers");
|
||||
|
||||
var etor = _timers.GetEnumerator();
|
||||
while (etor.MoveNext())
|
||||
{
|
||||
var timer = etor.Current.Value;
|
||||
|
||||
timer.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
public void ResumeAllTimers()
|
||||
{
|
||||
Debug.Log($"[TimerMgr]ResumeAllTimers");
|
||||
|
||||
var etor = _timers.GetEnumerator();
|
||||
while (etor.MoveNext())
|
||||
{
|
||||
var timer = etor.Current.Value;
|
||||
|
||||
timer.Resume();
|
||||
}
|
||||
}
|
||||
|
||||
// update all the registered timers on every frame
|
||||
private void Update()
|
||||
{
|
||||
if (_timersToAdd.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < _timersToAdd.Count; i++)
|
||||
{
|
||||
_timers.Add(_timerID++, _timersToAdd[i]);
|
||||
}
|
||||
|
||||
_timersToAdd.Clear();
|
||||
}
|
||||
|
||||
_timersToRemove.Clear();
|
||||
|
||||
var etor = _timers.GetEnumerator();
|
||||
while (etor.MoveNext())
|
||||
{
|
||||
var timer = etor.Current.Value;
|
||||
|
||||
timer.Update();
|
||||
|
||||
if (timer.isDone)
|
||||
{
|
||||
_timersToRemove.Add(etor.Current.Key);
|
||||
}
|
||||
}
|
||||
|
||||
if (_timersToRemove.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < _timersToRemove.Count; i++)
|
||||
{
|
||||
_timers.Remove(_timersToRemove[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TimerCount = _timers.Count;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
public static class TimerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Attach a timer on to the behaviour. If the behaviour is destroyed before the timer is completed,
|
||||
/// e.g. through a scene change, the timer callback will not execute.
|
||||
/// </summary>
|
||||
/// <param name="behaviour">The behaviour to attach this timer to.</param>
|
||||
/// <param name="duration">The duration to wait before the timer fires.</param>
|
||||
/// <param name="onComplete">The action to run when the timer elapses.</param>
|
||||
/// <param name="onUpdate">A function to call each tick of the timer. Takes the number of seconds elapsed since
|
||||
/// the start of the current cycle.</param>
|
||||
/// <param name="isLooped">Whether the timer should restart after executing.</param>
|
||||
/// <param name="useRealTime">Whether the timer uses real-time(not affected by slow-mo or pausing) or
|
||||
/// game-time(affected by time scale changes).</param>
|
||||
public static Timer AttachTimer(this MonoBehaviour behaviour, float duration, Action onComplete,
|
||||
Action<float> onUpdate = null, bool isLooped = false, bool useRealTime = false)
|
||||
{
|
||||
return Timer.Register(duration, onComplete, onUpdate, isLooped, useRealTime, behaviour);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Core/UnityTimer.cs.meta
Normal file
11
Assets/Scripts/Core/UnityTimer.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96b0c5856df7d62488eef989a3453c60
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
251
Assets/Scripts/Core/VibrationController.cs
Normal file
251
Assets/Scripts/Core/VibrationController.cs
Normal file
@@ -0,0 +1,251 @@
|
||||
using UnityEngine;
|
||||
using asap.core;
|
||||
using game;
|
||||
using UniRx;
|
||||
using System;
|
||||
using MoreMountains.NiceVibrations;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class VibrationData
|
||||
{
|
||||
public VibrationData(HapticTypes hapticTypes)
|
||||
{
|
||||
this.hapticTypes = hapticTypes;
|
||||
}
|
||||
public HapticTypes hapticTypes { get; set; }
|
||||
public VibrationData(int id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
public int id { get; set; }
|
||||
}
|
||||
|
||||
public class VibrationController
|
||||
{
|
||||
|
||||
IDisposable disposable;
|
||||
public void Init()
|
||||
{
|
||||
disposable = GContext.OnEvent<VibrationData>().Subscribe(OnVibrationData);
|
||||
|
||||
Debug.Log("[VibrationController] Init iOSInitializeHaptics");
|
||||
MMVibrationManager.iOSInitializeHaptics();
|
||||
}
|
||||
void OnVibrationData(VibrationData data)
|
||||
{
|
||||
bool isVibrate = GContext.container.Resolve<ISettingService>().Vibration;
|
||||
if (isVibrate)
|
||||
{
|
||||
if (data.id > 0)
|
||||
{
|
||||
PlayVibrationList(data.id);
|
||||
return;
|
||||
}
|
||||
switch (data.hapticTypes)
|
||||
{
|
||||
case HapticTypes.Selection:
|
||||
case HapticTypes.Success:
|
||||
case HapticTypes.Warning:
|
||||
case HapticTypes.Failure:
|
||||
case HapticTypes.LightImpact:
|
||||
case HapticTypes.MediumImpact:
|
||||
case HapticTypes.HeavyImpact:
|
||||
case HapticTypes.SoftImpact:
|
||||
case HapticTypes.RigidImpact:
|
||||
MMVibrationManager.Haptic(data.hapticTypes);
|
||||
break;
|
||||
case HapticTypes.Vibrate:
|
||||
MMVibrationManager.Vibrate();
|
||||
break;
|
||||
default:
|
||||
#if UNITY_IOS || UNITY_ANDROID
|
||||
Handheld.Vibrate();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~VibrationController()
|
||||
{
|
||||
disposable.Dispose();
|
||||
disposable = null;
|
||||
MMVibrationManager.iOSReleaseHaptics();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the default Unity vibration, without any control over duration, pattern or amplitude
|
||||
/// </summary>
|
||||
public void TriggerDefault()
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
#if UNITY_IOS || UNITY_ANDROID
|
||||
Handheld.Vibrate();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the default Vibrate method, which will result in a medium vibration on Android and a medium impact on iOS
|
||||
/// </summary>
|
||||
public void TriggerVibrate()
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
MMVibrationManager.Vibrate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the selection haptic feedback, a light vibration on Android, and a light impact on iOS
|
||||
/// </summary>
|
||||
public void TriggerSelection()
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
MMVibrationManager.Haptic(HapticTypes.Selection);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the success haptic feedback, a light then heavy vibration on Android, and a success impact on iOS
|
||||
/// </summary>
|
||||
public void TriggerSuccess()
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
MMVibrationManager.Haptic(HapticTypes.Success);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the warning haptic feedback, a heavy then medium vibration on Android, and a warning impact on iOS
|
||||
/// </summary>
|
||||
public void TriggerWarning()
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
MMVibrationManager.Haptic(HapticTypes.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers the failure haptic feedback, a medium / heavy / heavy / light vibration pattern on Android, and a failure impact on iOS
|
||||
/// </summary>
|
||||
public void TriggerFailure()
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
MMVibrationManager.Haptic(HapticTypes.Failure);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers a light impact on iOS and a short and light vibration on Android.
|
||||
/// </summary>
|
||||
public void TriggerLightImpact()
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
MMVibrationManager.Haptic(HapticTypes.LightImpact);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers a medium impact on iOS and a medium and regular vibration on Android.
|
||||
/// </summary>
|
||||
public void TriggerMediumImpact()
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
MMVibrationManager.Haptic(HapticTypes.MediumImpact);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers a heavy impact on iOS and a long and heavy vibration on Android.
|
||||
/// </summary>
|
||||
public void TriggerHeavyImpact()
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
MMVibrationManager.Haptic(HapticTypes.HeavyImpact);
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerSoftImpact()
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
MMVibrationManager.Haptic(HapticTypes.SoftImpact);
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerRigidImpact()
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
MMVibrationManager.Haptic(HapticTypes.RigidImpact);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsVibrate
|
||||
{
|
||||
get
|
||||
{
|
||||
ISettingService settingService = GContext.container.Resolve<ISettingService>();
|
||||
return settingService.Vibration;
|
||||
}
|
||||
}
|
||||
async void PlayVibrationList(int id)
|
||||
{
|
||||
if (IsVibrate)
|
||||
{
|
||||
cfg.Tables tables = GContext.container.Resolve<cfg.Tables>();
|
||||
if (tables != null)
|
||||
{
|
||||
cfg.VibrationDef vibrationDef = tables.TbVibrationDef.GetOrDefault(id);
|
||||
if (vibrationDef != null)
|
||||
{
|
||||
List<string> VibrationList = vibrationDef.VibrationList;
|
||||
List<float> DelayList = vibrationDef.DelayList;
|
||||
for (int i = 0; i < VibrationList.Count; i++)
|
||||
{
|
||||
await Awaiters.Seconds(DelayList[i]);
|
||||
OnVibrationData(VibrationList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnVibrationData(string hapticTypes)
|
||||
{
|
||||
bool success = Enum.TryParse(hapticTypes, out HapticTypes value);
|
||||
if (success)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case HapticTypes.Selection:
|
||||
case HapticTypes.Success:
|
||||
case HapticTypes.Warning:
|
||||
case HapticTypes.Failure:
|
||||
case HapticTypes.LightImpact:
|
||||
case HapticTypes.MediumImpact:
|
||||
case HapticTypes.HeavyImpact:
|
||||
case HapticTypes.SoftImpact:
|
||||
case HapticTypes.RigidImpact:
|
||||
MMVibrationManager.Haptic(value);
|
||||
break;
|
||||
case HapticTypes.Vibrate:
|
||||
MMVibrationManager.Vibrate();
|
||||
break;
|
||||
default:
|
||||
#if UNITY_IOS || UNITY_ANDROID
|
||||
Handheld.Vibrate();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/Core/VibrationController.cs.meta
Normal file
11
Assets/Scripts/Core/VibrationController.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73f660bbef6338449b1155c9e17131fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -250
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user