├── .DS_Store ├── 2Dfx.unitypackage ├── AdManager.cs ├── Advanced PlayerPrefs Window v1.9.8.unitypackage ├── Animation_base.cs ├── BGLoop.cs ├── CameraAim.cs ├── CameraMove.cs ├── CameraShake.cs ├── FacebookManager.cs ├── FelexiableLayoutGroup.cs ├── Final IK.unitypackage ├── FixIphoneX.cs ├── Food.unitypackage ├── IAPManager.cs ├── InputManager.cs ├── InvertMaskUI.cs ├── JoyStick.cs ├── KDL.txt ├── Laser.unitypackage ├── LazyPooling.cs ├── MaterialExtensions.cs ├── Nice_Vibrations_Haptic_Feedback_for_Mobile_Gamepads_v3_9_unitypackage.file ├── NotiManager ├── IGameNotification.cs └── NotiManager.cs ├── ObjectPoolingX.cs ├── ObjectPooling_base.cs ├── Paralax.cs ├── ParticalControll.cs ├── PathCreater.cs ├── PathCreator ├── MovingFollowPath.cs ├── PathCreator.cs ├── PathEditor.cs └── README.md ├── Pathfinding.cs ├── README.md ├── RotateEffect.cs ├── SerializableDictionary.cs ├── ShowDebug.unitypackage ├── SimpleJSON.cs ├── Singleton.cs ├── Sound.zip ├── Sound ├── DestroySound.cs └── SoundManager.cs ├── ThrowObject.cs ├── Trans_Text.cs ├── Transperant Shader ├── HuynnShader.shader └── MaterialExtensions.cs ├── UnityMainThread.cs ├── VisionCone.cs └── skybox.unitypackage /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhathuy7996/ReUseScript_Unity/4aa91d90bf757c82774baf3a3bb86d4ea2a514ef/.DS_Store -------------------------------------------------------------------------------- /2Dfx.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhathuy7996/ReUseScript_Unity/4aa91d90bf757c82774baf3a3bb86d4ea2a514ef/2Dfx.unitypackage -------------------------------------------------------------------------------- /AdManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.Events; 5 | using GoogleMobileAds.Api; 6 | 7 | public class AdManager : MonoBehaviour 8 | { 9 | string AppID = "ca-app-pub-9056640292640134~3154610018",//"ca-app-pub-3940256099942544~3347511713", 10 | BannerID = "ca-app-pub-3940256099942544/6300978111",//"ca-app-pub-3940256099942544/6300978111", 11 | InterID = "ca-app-pub-3940256099942544/1033173712",//"ca-app-pub-3940256099942544/1033173712", 12 | VideoID = "ca-app-pub-3940256099942544/5224354917";//"ca-app-pub-3940256099942544/5224354917"; 13 | 14 | [Header("AdUnit")] 15 | [SerializeField] private InterstitialAd interstitial = null; 16 | private List RewardAds = new List(); 17 | [SerializeField] int MaxReward = 3; 18 | 19 | public UnityEvent RewardCallBack = null, InterCallBack = null; 20 | private BannerView bannerAd = null; 21 | 22 | private bool _Banner_active = false, _InterShowed = false; 23 | float TimeInter = 0; 24 | [SerializeField] float MaxTimerInter = 60; 25 | public bool Banner_active => _Banner_active; 26 | public bool InterShowed => _InterShowed; 27 | 28 | float DelayReloadInter = 1, DelayReloadReward = 1, DelayReloadBanner = 1; 29 | 30 | void Start() { 31 | MobileAds.Initialize(this.AppID); 32 | 33 | this.RequestInterstitial(); 34 | //this.RequestBanner(); 35 | 36 | for (int i = 0; i < MaxReward; i++) { 37 | RewardAds.Add(this.RequestReward()); 38 | } 39 | } 40 | 41 | void Update() { 42 | if (_InterShowed) { 43 | TimeInter += Time.deltaTime; 44 | if (TimeInter >= MaxTimerInter) 45 | { 46 | TimeInter = 0; 47 | _InterShowed = false; 48 | } 49 | } 50 | } 51 | 52 | #region Banner 53 | public void RequestBanner() 54 | { 55 | Debug.LogError("Banner request!!"); 56 | // Create a 320x50 banner at the top of the screen. 57 | bannerAd = new BannerView(this.BannerID, AdSize.SmartBanner, AdPosition.Top); 58 | 59 | // Called when an ad request has successfully loaded. 60 | bannerAd.OnAdLoaded += Banner_HandleOnAdLoaded; 61 | // Called when an ad request failed to load. 62 | bannerAd.OnAdFailedToLoad += Banner_HandleOnAdFailedToLoad; 63 | 64 | // Create an empty ad request. 65 | AdRequest request = new AdRequest.Builder().Build(); 66 | 67 | // Load the banner with the request. 68 | bannerAd.LoadAd(request); 69 | } 70 | #endregion 71 | 72 | #region Handle Banner 73 | public void Banner_HandleOnAdLoaded(object sender, System.EventArgs args) 74 | { 75 | Debug.LogError("Load banner success!"); 76 | _Banner_active = true; 77 | } 78 | 79 | public void Banner_HandleOnAdFailedToLoad(object sender, AdFailedToLoadEventArgs args) 80 | { 81 | Debug.LogError("Load banner faild"); 82 | Invoke("RequestBanner", DelayReloadBanner); 83 | DelayReloadBanner *= 5; 84 | } 85 | #endregion 86 | 87 | #region Inter 88 | public void RequestInterstitial() 89 | { 90 | if (this.interstitial != null) { 91 | this.interstitial.Destroy(); 92 | } 93 | // Initialize an InterstitialAd. 94 | this.interstitial = new InterstitialAd(InterID); 95 | 96 | // Called when an ad request has successfully loaded. 97 | this.interstitial.OnAdLoaded += Inter_HandleOnAdLoaded; 98 | // Called when an ad request failed to load. 99 | this.interstitial.OnAdFailedToLoad += Inter_HandleOnAdFailedToLoad; 100 | // Called when an ad is shown. 101 | this.interstitial.OnAdOpening += Inter_HandleOnAdOpened; 102 | // Called when the ad is closed. 103 | this.interstitial.OnAdClosed += Inter_HandleOnAdClosed; 104 | // Called when the ad click caused the user to leave the application. 105 | this.interstitial.OnAdLeavingApplication += Inter_HandleOnAdLeavingApplication; 106 | 107 | // Create an empty ad request. 108 | AdRequest request = new AdRequest.Builder().Build(); 109 | // Load the interstitial with the request. 110 | this.interstitial.LoadAd(request); 111 | 112 | Debug.LogError("Inter requested"); 113 | StartCoroutine(WaitLoadInter()); 114 | } 115 | 116 | IEnumerator WaitLoadInter() { 117 | yield return new WaitUntil(() => this.interstitial.IsLoaded()); 118 | Debug.LogError("Inter load done!"); 119 | } 120 | 121 | public void ShowInter() 122 | { 123 | if (this.interstitial.IsLoaded()) { 124 | 125 | if (_InterShowed) 126 | return; 127 | _InterShowed = true; 128 | TimeInter = 0; 129 | this.interstitial.Show(); 130 | } 131 | } 132 | #endregion 133 | 134 | #region HandleInter 135 | 136 | public void Inter_HandleOnAdLoaded(object sender, System.EventArgs args) 137 | { 138 | MonoBehaviour.print("Inter HandleAdLoaded event received"); 139 | 140 | } 141 | 142 | public void Inter_HandleOnAdFailedToLoad(object sender, AdFailedToLoadEventArgs args) 143 | { 144 | MonoBehaviour.print("inter HandleFailedToReceiveAd event received with message: "); 145 | Invoke("RequestInterstitial", DelayReloadInter); 146 | DelayReloadInter *= 2; 147 | } 148 | 149 | public void Inter_HandleOnAdOpened(object sender, System.EventArgs args) 150 | { 151 | MonoBehaviour.print("Inter HandleAdOpened event received"); 152 | 153 | } 154 | 155 | public void Inter_HandleOnAdClosed(object sender, System.EventArgs args) 156 | { 157 | MonoBehaviour.print("HandleAdClosed event received"); 158 | RequestInterstitial(); 159 | if (InterCallBack != null) { 160 | InterCallBack.Invoke(); 161 | InterCallBack.RemoveAllListeners(); 162 | } 163 | 164 | } 165 | 166 | public void Inter_HandleOnAdLeavingApplication(object sender, System.EventArgs args) 167 | { 168 | MonoBehaviour.print("HandleAdLeavingApplication event received"); 169 | RequestInterstitial(); 170 | } 171 | #endregion 172 | 173 | #region Reward 174 | public RewardedAd RequestReward() 175 | { 176 | 177 | RewardedAd rewardedAd = new RewardedAd(VideoID); 178 | 179 | rewardedAd.OnAdLoaded += HandleRewardedAdLoaded; 180 | rewardedAd.OnUserEarnedReward += HandleUserEarnedReward; 181 | rewardedAd.OnAdClosed += HandleRewardedAdClosed; 182 | 183 | // Create an empty ad request. 184 | AdRequest request = new AdRequest.Builder().Build(); 185 | // Load the rewarded ad with the request. 186 | rewardedAd.LoadAd(request); 187 | 188 | Debug.Log("Reward requested"); 189 | 190 | return rewardedAd; 191 | } 192 | 193 | public void ShowReward() 194 | { 195 | #if UNITY_EDITOR 196 | if (RewardCallBack != null) 197 | { 198 | RewardCallBack.Invoke(); 199 | RewardCallBack.RemoveAllListeners(); 200 | } 201 | return; 202 | #endif 203 | RewardedAd R = CheckAvailableReward(); 204 | if (R != null) { 205 | R.Show(); 206 | return; 207 | } 208 | if (RewardCallBack != null) 209 | { 210 | RewardCallBack.RemoveAllListeners(); 211 | } 212 | Debug.LogError("Not avaiable reward!"); 213 | } 214 | 215 | public RewardedAd CheckAvailableReward() { 216 | foreach (RewardedAd R in this.RewardAds) { 217 | if (R.IsLoaded()) { 218 | return R; 219 | } 220 | } 221 | if (this.RewardAds.Count < MaxReward) 222 | RewardAds.Add(this.RequestReward()); 223 | return null; 224 | } 225 | 226 | #endregion 227 | 228 | #region HandleReward 229 | 230 | public void HandleRewardedAdLoaded(object sender, System.EventArgs args) 231 | { 232 | Debug.Log("HandleRewardedAdLoaded event received"); 233 | } 234 | 235 | public void HandleRewardedAdFailedToLoad(object sender, AdErrorEventArgs args) 236 | { 237 | Debug.Log("HandleRewardedAdFailedToLoad event received with message: " 238 | + args.Message); 239 | this.RewardAds.Remove((RewardedAd)sender); 240 | Invoke("CheckAvailableReward", DelayReloadReward); 241 | DelayReloadReward *= 2; 242 | } 243 | 244 | public void HandleRewardedAdOpening(object sender, System.EventArgs args) 245 | { 246 | Debug.Log("HandleRewardedAdOpening event received"); 247 | } 248 | 249 | public void HandleRewardedAdFailedToShow(object sender, AdErrorEventArgs args) 250 | { 251 | Debug.Log("HandleRewardedAdFailedToShow event received with message: "); 252 | if (RewardCallBack != null) 253 | { 254 | RewardCallBack.RemoveAllListeners(); 255 | } 256 | } 257 | 258 | public void HandleRewardedAdClosed(object sender, System.EventArgs args) 259 | { 260 | Debug.Log("HandleRewardedAdClosed event received"); 261 | this.RewardAds.Remove((RewardedAd)sender); 262 | CheckAvailableReward(); 263 | 264 | } 265 | 266 | public void HandleUserEarnedReward(object sender, Reward args) 267 | { 268 | 269 | Debug.Log("HandleRewardedAdRewarded event received for "); 270 | if (RewardCallBack != null) { 271 | StartCoroutine(RunRewardCallBack()); 272 | } 273 | this.RewardAds.Remove((RewardedAd)sender); 274 | CheckAvailableReward(); 275 | } 276 | private IEnumerator RunRewardCallBack() 277 | { 278 | yield return null; 279 | RewardCallBack.Invoke(); 280 | RewardCallBack.RemoveAllListeners(); 281 | } 282 | #endregion 283 | 284 | } 285 | -------------------------------------------------------------------------------- /Advanced PlayerPrefs Window v1.9.8.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhathuy7996/ReUseScript_Unity/4aa91d90bf757c82774baf3a3bb86d4ea2a514ef/Advanced PlayerPrefs Window v1.9.8.unitypackage -------------------------------------------------------------------------------- /Animation_base.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class Animation_base : MonoBehaviour 6 | { 7 | Animation Anim = null; 8 | void OnEnable(){ 9 | StartCoroutine(Wait()); 10 | } 11 | // Start is called before the first frame update 12 | void Awake() 13 | { 14 | Anim = this.GetComponent(); 15 | } 16 | 17 | // Update is called once per frame 18 | void Update() 19 | { 20 | 21 | } 22 | 23 | IEnumerator Wait(){ 24 | yield return new WaitUntil(()=> !Anim.isPlaying); 25 | this.gameObject.SetActive(false); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /BGLoop.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class BGLoop : MonoBehaviour 6 | { 7 | Camera _mainCam; 8 | SpriteRenderer _spriteRenderer; 9 | 10 | [SerializeField] 11 | float _widthImage; 12 | // Start is called before the first frame update 13 | void Start() 14 | { 15 | _mainCam = Camera.main; 16 | _spriteRenderer = this.GetComponent(); 17 | Texture image = _spriteRenderer.sprite.texture; 18 | 19 | _widthImage = image.width / _spriteRenderer.sprite.pixelsPerUnit; 20 | } 21 | 22 | // Update is called once per frame 23 | void Update() 24 | { 25 | if (Mathf.Abs(_mainCam.transform.position.x - this.transform.position.x) > _widthImage) 26 | { 27 | float offset = Mathf.Abs(_mainCam.transform.position.x - this.transform.position.x) - _widthImage ; 28 | this.transform.position = new Vector2(_mainCam.transform.position.x +offset , this.transform.position.y); 29 | Debug.Log(offset); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /CameraAim.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | using System.Linq; 6 | using System; 7 | 8 | public class CameraAim : MonoBehaviour 9 | { 10 | 11 | [SerializeField] Transform _player; 12 | Camera _cam; 13 | 14 | 15 | [Header("---------")] 16 | [Space(10)] 17 | 18 | [SerializeField] LayerMask _layerMask; 19 | 20 | [SerializeField] 21 | GameObject _oldGameObject, _currentGameObject; 22 | // Start is called before the first frame update 23 | void Start() 24 | { 25 | 26 | _cam = Camera.main; 27 | } 28 | 29 | // Update is called once per frame 30 | void Update() 31 | { 32 | 33 | 34 | Vector3 dir = _cam.transform.position - _player.transform.position; 35 | Debug.DrawRay(_player.transform.position, dir*5,Color.red); 36 | RaycastHit hit; 37 | if(Physics.Raycast(_player.transform.position, dir.normalized,out hit, dir.sqrMagnitude, _layerMask)) 38 | { 39 | if (hit.collider != null) 40 | { 41 | 42 | _currentGameObject = hit.collider.gameObject; 43 | 44 | }else 45 | _currentGameObject = null; 46 | } 47 | else 48 | { 49 | _currentGameObject = null; 50 | } 51 | 52 | 53 | if(_currentGameObject == null) 54 | { 55 | if (_oldGameObject != null) 56 | setMaterialAlpha(_oldGameObject, 1); 57 | return; 58 | } 59 | 60 | setMaterialAlpha(_currentGameObject, 0.5f); 61 | if (_currentGameObject.Equals(_oldGameObject)) 62 | return; 63 | 64 | if(_oldGameObject != null) 65 | setMaterialAlpha(_oldGameObject, 1); 66 | 67 | _oldGameObject = _currentGameObject; 68 | } 69 | 70 | void setMaterialAlpha(GameObject g, float alpha) 71 | { 72 | List Mats = new List(); 73 | Renderer r = g.GetComponent(); 74 | if (r != null) 75 | Mats.AddRange(getMaterials(r)); 76 | 77 | Renderer[] renderers = g.GetComponentsInChildren(); 78 | foreach (Renderer _r in renderers) 79 | { 80 | Mats.AddRange(getMaterials(_r)); 81 | } 82 | 83 | ChangeAlpha(Mats, alpha); 84 | 85 | } 86 | 87 | 88 | 89 | List getMaterials(Renderer r) 90 | { 91 | return r.materials.ToList(); 92 | } 93 | 94 | void ChangeAlpha(List mats, float alphaVal) 95 | { 96 | foreach (Material mat in mats) 97 | { 98 | if (alphaVal == 1) 99 | mat.ToOpaqueMode(); 100 | else 101 | mat.ToFadeMode(); 102 | Color oldColor = mat.color; 103 | Color newColor = new Color(oldColor.r, oldColor.g, oldColor.b, alphaVal); 104 | 105 | try 106 | { 107 | mat.SetColor("_Color", newColor); 108 | } 109 | catch (Exception e) 110 | { 111 | 112 | } 113 | } 114 | 115 | 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /CameraMove.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class CameraMove : MonoBehaviour { 6 | public float damping = 1.5f; 7 | public Transform _target; 8 | public Vector3 offset = new Vector3(2f, 1f); 9 | 10 | private bool faceLeft; 11 | private int lastX; 12 | private float dynamicSpeed; 13 | private Camera _cam; 14 | 15 | void Start() 16 | { 17 | offset = new Vector2(Mathf.Abs(offset.x), offset.y); 18 | FindPlayer(); 19 | _cam = gameObject.GetComponent(); 20 | } 21 | 22 | public void FindPlayer() 23 | { 24 | lastX = Mathf.RoundToInt(_target.position.x); 25 | transform.position = new Vector3(_target.position.x + offset.x, _target.position.y + offset.y, _target.position.z + offset.z); 26 | } 27 | 28 | void FixedUpdate() 29 | { 30 | if (_target) 31 | { 32 | int currentX = Mathf.RoundToInt(_target.position.x); 33 | if (currentX > lastX) faceLeft = false; else if (currentX < lastX) faceLeft = true; 34 | lastX = Mathf.RoundToInt(_target.position.x); 35 | 36 | Vector3 target; 37 | if (faceLeft) 38 | { 39 | target = new Vector3(_target.position.x - offset.x, _target.position.y + offset.y+dynamicSpeed, _target.position.z + offset.z+dynamicSpeed); 40 | } 41 | else 42 | { 43 | target = new Vector3(_target.position.x + offset.x, _target.position.y + offset.y+dynamicSpeed, _target.position.z + offset.z+dynamicSpeed); 44 | } 45 | Vector3 currentPosition = Vector3.Lerp(transform.position, target, damping * Time.deltaTime); 46 | transform.position = currentPosition; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /CameraShake.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using UnityEngine.Events; 6 | 7 | public class CameraShake : MonoBehaviour 8 | { 9 | // Transform of the camera to shake. Grabs the gameObject's transform 10 | // if null. 11 | Transform camTransform; 12 | 13 | // How long the object should shake for. 14 | float _shakeDuration = 0f; 15 | public float shakeDuration => _shakeDuration; 16 | [SerializeField] 17 | List BG_Color = new List(); 18 | 19 | [SerializeField] 20 | // Amplitude of the shake. A larger value shakes the camera harder. 21 | float shakeAmount = 0.7f, decreaseFactor = 1.0f; 22 | 23 | public UnityEvent ShakeDone = null; 24 | 25 | Vector3 originalPos; 26 | 27 | void Awake() 28 | { 29 | if (camTransform == null) 30 | { 31 | camTransform = GetComponent(typeof(Transform)) as Transform; 32 | } 33 | } 34 | 35 | void OnEnable() 36 | { 37 | originalPos = camTransform.localPosition; 38 | } 39 | 40 | void Update() 41 | { 42 | if (_shakeDuration > 0) 43 | { 44 | camTransform.localPosition = originalPos + Random.insideUnitSphere * shakeAmount; 45 | _shakeDuration -= Time.deltaTime * decreaseFactor; 46 | Camera.main.backgroundColor = BG_Color[1]; 47 | } 48 | else 49 | { 50 | _shakeDuration = 0f; 51 | camTransform.localPosition = originalPos; 52 | Camera.main.backgroundColor = BG_Color[0]; 53 | } 54 | } 55 | 56 | public void Shake(float timeDur){ 57 | _shakeDuration = timeDur; 58 | StartCoroutine(CallEventDone()); 59 | } 60 | 61 | IEnumerator CallEventDone(){ 62 | yield return new WaitForSeconds(_shakeDuration); 63 | if(ShakeDone != null){ 64 | ShakeDone.Invoke(); 65 | ShakeDone.RemoveAllListeners(); 66 | } 67 | 68 | } 69 | } -------------------------------------------------------------------------------- /FacebookManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using Facebook.Unity; 5 | 6 | public class FacebookManager : Singleton 7 | { 8 | void Awake () 9 | { 10 | 11 | if (FB.IsInitialized) { 12 | FB.ActivateApp(); 13 | } else { 14 | //Handle FB.Init 15 | FB.Init( () => { 16 | FB.ActivateApp(); 17 | 18 | }); 19 | } 20 | 21 | } 22 | 23 | 24 | void Start() 25 | { 26 | DontDestroyOnLoad(this); 27 | } 28 | 29 | 30 | 31 | public void LogEvent(string EventName){ 32 | 33 | try{ 34 | if (FB.IsInitialized) { 35 | FB.LogAppEvent(EventName,1f); 36 | } else { 37 | //Handle FB.Init 38 | FB.Init( () => { 39 | FB.ActivateApp(); 40 | FB.LogAppEvent(EventName,1f); 41 | }); 42 | } 43 | }catch(System.Exception e){ 44 | Debug.LogError(e); 45 | } 46 | 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /FelexiableLayoutGroup.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | 6 | namespace DVAH.Lib{ 7 | public class FelexiableLayoutGroup : LayoutGroup 8 | { 9 | public FitType fitType; 10 | public int rows, columns; 11 | public Vector2 cellSize, spacing; 12 | public bool FitX, FitY; 13 | 14 | public override void CalculateLayoutInputVertical() 15 | { 16 | 17 | if(fitType == FitType.Width || fitType == FitType.Heigh || fitType == FitType.Uniform) 18 | { 19 | FitX = true; 20 | FitY = true; 21 | float sqrRt = Mathf.Sqrt(this.transform.childCount); 22 | rows = Mathf.CeilToInt(sqrRt); 23 | columns = Mathf.CeilToInt(sqrRt); 24 | } 25 | 26 | if (fitType == FitType.Width || fitType == FitType.FixedColum) 27 | { 28 | rows = Mathf.CeilToInt(transform.childCount / (float)columns); 29 | } 30 | 31 | if (fitType == FitType.Heigh || fitType == FitType.FixedRow) 32 | { 33 | columns = Mathf.CeilToInt(transform.childCount / (float)rows); 34 | } 35 | 36 | 37 | 38 | float parentWidth = rectTransform.rect.width; 39 | float parentHeight = rectTransform.rect.height; 40 | 41 | float cellWidth = (parentWidth - (spacing.x * (columns - 1)) - padding.left - padding.right) / (float)columns ; 42 | float cellHeight = (parentHeight - (spacing.y * (rows -1) - padding.top - padding.bottom) ) / (float)rows ; 43 | 44 | cellSize.x = FitX ? cellWidth : cellSize.x; 45 | cellSize.y = FitY ? cellHeight : cellSize.y; 46 | 47 | int columnCount = 0, rowCount = 0; 48 | bool isCenter = (int)childAlignment == 1 || (int)childAlignment == 4 || (int)childAlignment == 7; 49 | for (int i = 0; i < rectChildren.Count; i++) 50 | { 51 | rowCount = i / columns; 52 | columnCount = i % columns; 53 | float center = 0; 54 | int leftOver = rectChildren.Count % columns; 55 | 56 | if(isCenter && (rowCount == rows - 1 && leftOver != 0)){ 57 | center = (parentWidth - cellSize.x * leftOver - spacing.x * (columns - 1) - padding.left - padding.right) / 2.0f; 58 | } 59 | 60 | var item = rectChildren[i]; 61 | var xPos = center + cellSize.x * columnCount + spacing.x * columnCount + padding.left; 62 | 63 | var yPos = cellSize.y * rowCount + spacing.y * rowCount + padding.top; 64 | 65 | 66 | 67 | SetChildAlongAxis(item, 0, xPos, cellSize.x); 68 | SetChildAlongAxis(item, 1, yPos, cellSize.y); 69 | } 70 | } 71 | 72 | public override void SetLayoutHorizontal() 73 | { 74 | 75 | 76 | 77 | } 78 | 79 | public override void SetLayoutVertical() 80 | { 81 | 82 | } 83 | 84 | public enum FitType 85 | { 86 | Uniform, 87 | Width, 88 | Heigh, 89 | FixedRow, 90 | FixedColum 91 | } 92 | 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Final IK.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhathuy7996/ReUseScript_Unity/4aa91d90bf757c82774baf3a3bb86d4ea2a514ef/Final IK.unitypackage -------------------------------------------------------------------------------- /FixIphoneX.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | 6 | public class FixIphoneX : MonoBehaviour 7 | { 8 | [SerializeField] 9 | bool _FixBottom, _FixTop = true, _FixBottom_withScale = false; 10 | [SerializeField] 11 | float _Bottom = 0; 12 | 13 | // Start is called before the first frame updated 14 | void Start() 15 | { 16 | if (_FixTop) 17 | this.GetComponent().offsetMax = new Vector2(this.GetComponent().offsetMax.x, -Screen.safeArea.y); 18 | 19 | if (_FixBottom_withScale) 20 | { 21 | this.GetComponent().offsetMin = new Vector2(this.GetComponent().offsetMin.x, Screen.height - Screen.safeArea.height); 22 | } 23 | 24 | if (_FixBottom) 25 | this.GetComponent().offsetMin = new Vector2(this.GetComponent().offsetMin.x, 0); 26 | 27 | 28 | 29 | } 30 | 31 | // Update is called once per frame 32 | void Update() 33 | { 34 | 35 | if (AdManager.Instant.Banner_active) 36 | { 37 | this.GetComponent().offsetMax = new Vector2(this.GetComponent().offsetMax.x, -adHeight()); 38 | if (_FixBottom) 39 | this.GetComponent().offsetMin = new Vector2(this.GetComponent().offsetMin.x, 0); 40 | } 41 | } 42 | 43 | public static float adHeight() 44 | { 45 | float f = Screen.dpi / 160f; 46 | float dp = Screen.height / f; 47 | return (dp > 720f) ? 90f * f 48 | : (dp > 400f) ? 50f * f 49 | : 32f * f; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Food.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhathuy7996/ReUseScript_Unity/4aa91d90bf757c82774baf3a3bb86d4ea2a514ef/Food.unitypackage -------------------------------------------------------------------------------- /IAPManager.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Threading.Tasks; 3 | using System; 4 | using UnityEngine.UIElements; 5 | #if !IAP 6 | namespace DVAH 7 | { 8 | 9 | public class IAPManager : Singleton 10 | { 11 | public void BuyProductID(string productId, Action onBuyDone = null) { 12 | Debug.LogError(CONSTANT.Prefix + "==>Mark using IAP on checklist menu or add IAP on define symbols!<=="); 13 | } 14 | 15 | public async Task TryAddRestoreEvent(string productID, Action eventRestore = null, bool isTimeOut = false) 16 | { 17 | Debug.LogError(CONSTANT.Prefix + "==>Mark using IAP on checklist menu or add IAP on define symbols!<=="); 18 | await Task.Delay(1000); 19 | 20 | return false; 21 | } 22 | 23 | } 24 | } 25 | #else 26 | using System.Collections.Generic; 27 | 28 | using UnityEngine.Purchasing; 29 | using UnityEngine.UI; 30 | using UnityEngine.Events; 31 | using UnityEngine.Purchasing.Security; 32 | using System.Collections; 33 | 34 | 35 | namespace DVAH 36 | { 37 | 38 | public class IAPManager : Singleton, IStoreListener 39 | { 40 | 41 | private static IStoreController m_StoreController; // The Unity Purchasing system. 42 | private static IExtensionProvider m_StoreExtensionProvider; // The store-specific Purchasing subsystems. 43 | 44 | List _restoreItemCheck = new List(); 45 | 46 | private Action _onBuyDone = null; 47 | 48 | public bool IsInitDone => IsInitialized(); 49 | private bool _isBuying = false; 50 | 51 | Action _onInitDone; 52 | public int PurchaseInfo = 0; 53 | protected override void Awake() 54 | { 55 | DontDestroyOnLoad(this); 56 | Debug.Log(CONSTANT.Prefix + $"==========>IAP start Init!<=========="); 57 | 58 | if (!ProductCatalog.LoadDefaultCatalog().enableCodelessAutoInitialization) 59 | InitializePurchasing(); 60 | } 61 | 62 | public void InitializePurchasing() 63 | { 64 | // If we have already connected to Purchasing ... 65 | if (IsInitialized()) 66 | { 67 | // ... we are done here. 68 | return; 69 | } 70 | 71 | // Create a builder, first passing in a suite of Unity provided stores. 72 | var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance()); 73 | 74 | 75 | 76 | var catalog = ProductCatalog.LoadDefaultCatalog(); 77 | 78 | foreach (var product in catalog.allValidProducts) 79 | { 80 | if (product.allStoreIDs.Count > 0) 81 | { 82 | var ids = new IDs(); 83 | foreach (var storeID in product.allStoreIDs) 84 | { 85 | ids.Add(storeID.id, storeID.store); 86 | } 87 | builder.AddProduct(product.id, product.type, ids); 88 | } 89 | else 90 | { 91 | builder.AddProduct(product.id, product.type); 92 | } 93 | 94 | 95 | } 96 | 97 | 98 | 99 | // Kick off the remainder of the set-up with an asynchrounous call, passing the configuration 100 | // and this class' instance. Expect a response either in OnInitialized or OnInitializeFailed. 101 | UnityPurchasing.Initialize(this, builder); 102 | 103 | } 104 | 105 | 106 | private bool IsInitialized() 107 | { 108 | // Only say we are initialized if both the Purchasing references are set. 109 | return m_StoreController != null && m_StoreExtensionProvider != null; 110 | } 111 | 112 | /// 113 | /// Restore product which user already purchase! 114 | /// 115 | /// ID of product (in catalog) 116 | /// action when product restore success 117 | /// await table Task, true if restore action done and false if wrong ID 118 | public async Task TryAddRestoreEvent(string productID, Action eventRestore = null, bool isTimeOut = false) 119 | { 120 | var catalog = ProductCatalog.LoadDefaultCatalog(); 121 | double countTime = 0; 122 | while (!_restoreItemCheck.Contains(productID) || !IsInitialized()) 123 | { 124 | countTime += 500; 125 | if (isTimeOut) 126 | if (countTime >= 360000f) 127 | { 128 | Debug.LogError(string.Format(CONSTANT.Prefix + "==>Restored product {0} fail, becuz time out! Check your network please!<==", productID)); 129 | return false; 130 | } 131 | await Task.Delay(500); 132 | } 133 | if (_restoreItemCheck.Contains(productID)) 134 | { 135 | UnityMainThread.wkr.AddJob(eventRestore); 136 | return true; 137 | } 138 | Debug.LogError(string.Format(CONSTANT.Prefix + "==>Restored product {0} fail, Check product ID!<==", productID)); 139 | return false; 140 | } 141 | 142 | /// 143 | /// Check if product is restored or not (maybe for hide button buy ...) 144 | /// 145 | /// ID of product (in catalog) 146 | /// true if product already buy or restored 147 | public bool CheckRestoredProduct(string productId) 148 | { 149 | return this._restoreItemCheck.Contains(productId); 150 | } 151 | 152 | 153 | /// 154 | /// Call if player click btn buy product 155 | /// 156 | /// ID of product (in catalog) 157 | /// do sth if buy done with a bool to describe success or not (example: add coin ...) 158 | public void BuyProductID(string productId, Action onBuyDone = null) 159 | { 160 | //onBuyDone?.Invoke(true); 161 | //return; 162 | BuyProductID(productId, (isSuccess, product) => { 163 | onBuyDone?.Invoke(isSuccess); 164 | }); 165 | } 166 | int level = 0; 167 | string screenName = ""; 168 | public void BuyProductID(string productId, Action onBuyDone = null) 169 | { 170 | if (_isBuying) return; 171 | 172 | _onBuyDone = onBuyDone; 173 | 174 | if (!string.IsNullOrEmpty(productId)) 175 | Debug.Log(CONSTANT.Prefix + $"==> buy productId : " + productId + " <=="); 176 | // If Purchasing has been initialized ... 177 | if (IsInitialized()) 178 | { 179 | 180 | _isBuying = true; 181 | // ... look up the Product reference with the general product identifier and the Purchasing 182 | // system's products collection. 183 | Product product = m_StoreController.products.WithID(productId); 184 | 185 | if (product != null && product.availableToPurchase) 186 | { 187 | //Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id)); 188 | // ... buy the product. Expect a response either through ProcessPurchase or OnPurchaseFailed 189 | // asynchronously. 190 | m_StoreController.InitiatePurchase(product, productId); 191 | return; 192 | } 193 | 194 | _isBuying = false; 195 | // ... report the product look-up failure situation 196 | Debug.LogError(CONSTANT.Prefix + $"==> BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase <=="); 197 | 198 | return; 199 | } 200 | 201 | // ... report the fact Purchasing has not succeeded initializing yet. Consider waiting longer or 202 | // retrying initiailization. 203 | _isBuying = false; 204 | Debug.LogError(CONSTANT.Prefix + $"==> BuyProductID FAIL. Not initialized <=="); 205 | //NoticeManager.Instance.LogNotice("BuyProductID FAIL. Not initialized."); 206 | 207 | } 208 | 209 | 210 | // Restore purchases previously made by this customer. Some platforms automatically restore purchases, like Google. 211 | // Apple currently requires explicit purchase restoration for IAP, conditionally displaying a password prompt. 212 | 213 | public void RestorePurchases() 214 | { 215 | // If Purchasing has not yet been set up ... 216 | if (!IsInitialized()) 217 | { 218 | // ... report the situation and stop restoring. Consider either waiting longer, or retrying initialization. 219 | Debug.LogError(CONSTANT.Prefix + $"==> RestorePurchases FAIL. Not initialized <=="); 220 | //NoticeManager.Instance.LogNotice("RestorePurchases FAIL. Not initialized."); 221 | return; 222 | } 223 | 224 | // If we are running on an Apple device ... 225 | if (Application.platform == RuntimePlatform.IPhonePlayer || 226 | Application.platform == RuntimePlatform.OSXPlayer) 227 | { 228 | // ... begin restoring purchases 229 | Debug.Log(CONSTANT.Prefix + $"==> RestorePurchases started ...<=="); 230 | 231 | // Fetch the Apple store-specific subsystem. 232 | var apple = m_StoreExtensionProvider.GetExtension(); 233 | // Begin the asynchronous process of restoring purchases. Expect a confirmation response in 234 | // the Action below, and ProcessPurchase if there are previously purchased products to restore. 235 | apple.RestoreTransactions((result) => 236 | { 237 | // The first phase of restoration. If no more responses are received on ProcessPurchase then 238 | // no purchases are available to be restored. 239 | Debug.Log(CONSTANT.Prefix + $"==> RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore <=="); 240 | }); 241 | } 242 | // Otherwise ... 243 | else 244 | { 245 | // We are not running on an Apple device. No work is necessary to restore purchases. 246 | Debug.LogError(CONSTANT.Prefix + $"==> RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform + " <=="); 247 | } 248 | } 249 | 250 | 251 | // 252 | // --- IStoreListener 253 | // 254 | 255 | public void OnInitialized(IStoreController controller, IExtensionProvider extensions) 256 | { 257 | // Purchasing has succeeded initializing. Collect our Purchasing references. 258 | // Overall Purchasing system, configured with products for this application. 259 | m_StoreController = controller; 260 | // Store specific subsystem, for accessing device-specific store features. 261 | m_StoreExtensionProvider = extensions; 262 | 263 | _onInitDone?.Invoke(); 264 | 265 | 266 | } 267 | public string GetPrice(string productId) 268 | { 269 | if (string.IsNullOrEmpty(productId)) return ""; 270 | if (m_StoreController != null) 271 | { 272 | string localizedPrice = m_StoreController.products.WithID(productId).metadata.localizedPriceString.ToString(); 273 | string price = ""; 274 | foreach (char a in localizedPrice) 275 | { 276 | if (Char.IsDigit(a)) 277 | { 278 | price += a; 279 | } 280 | else if (a.ToString() == "." || a.ToString() == ",") 281 | { 282 | price += a; 283 | } 284 | } 285 | 286 | return price; 287 | } 288 | else 289 | { 290 | return ""; 291 | } 292 | 293 | } 294 | public string GetCurrency(string productId) 295 | { 296 | if (string.IsNullOrEmpty(productId)) return ""; 297 | if (m_StoreController != null) 298 | { 299 | return m_StoreController.products.WithID(productId).metadata.isoCurrencyCode; 300 | } 301 | else 302 | { 303 | return ""; 304 | } 305 | 306 | } 307 | 308 | public void OnInitializeFailed(InitializationFailureReason error) 309 | { 310 | // Purchasing set-up has not succeeded. Check error for reason. Consider sharing this reason with the user. 311 | Debug.LogError(CONSTANT.Prefix + $"==> OnInitializeFailed InitializationFailureReason:" + error + " <=="); 312 | _onInitDone?.Invoke(); 313 | } 314 | 315 | 316 | public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) 317 | { 318 | 319 | var catalog = ProductCatalog.LoadDefaultCatalog(); 320 | foreach (var product in catalog.allValidProducts) 321 | { 322 | 323 | if (String.Equals(args.purchasedProduct.definition.id, product.id, StringComparison.Ordinal)) 324 | { 325 | Debug.Log(string.Format(CONSTANT.Prefix + "==> ProcessPurchase: PASS. Product: '{0}' <==", args.purchasedProduct.definition.id)); 326 | //NoticeManager.Instance.LogNotice(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id)); 327 | //#if UNITY_EDITOR 328 | 329 | if (!_restoreItemCheck.Contains(product.id)) 330 | { 331 | lock (_restoreItemCheck) 332 | { 333 | _restoreItemCheck.Add(product.id); 334 | } 335 | } 336 | 337 | try 338 | { 339 | _onBuyDone?.Invoke(true, args.purchasedProduct); 340 | _onBuyDone = null; 341 | } 342 | catch (Exception e) 343 | { 344 | Debug.LogError(CONSTANT.Prefix + "==> Buy production success but fail on invoke callback, error: " + e.Message); 345 | } 346 | 347 | 348 | 349 | _isBuying = false; 350 | return PurchaseProcessingResult.Complete; 351 | 352 | } 353 | } 354 | 355 | _isBuying = false; 356 | // Return a flag indicating whether this product has completely been received, or if the application needs 357 | // to be reminded of this purchase at next app launch. Use PurchaseProcessingResult.Pending when still 358 | // saving purchased products to the cloud, and when that save is delayed. 359 | return PurchaseProcessingResult.Pending; 360 | } 361 | 362 | 363 | public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason) 364 | { 365 | // A product purchase attempt did not succeed. Check failureReason for more detail. Consider sharing 366 | // this reason with the user to guide their troubleshooting actions. 367 | _isBuying = false; 368 | Debug.LogError(string.Format(CONSTANT.Prefix + "==> OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1} <==", product.definition.storeSpecificId, failureReason)); 369 | 370 | try 371 | { 372 | _onBuyDone?.Invoke(false, null); 373 | _onBuyDone = null; 374 | } 375 | catch (Exception e) 376 | { 377 | Debug.LogError(CONSTANT.Prefix + "==> Buy production fail then fail on invoke callback, error: " + e.Message); 378 | } 379 | 380 | 381 | } 382 | 383 | public void OnInitializeFailed(InitializationFailureReason error, string message) 384 | { 385 | Debug.LogError(CONSTANT.Prefix + "==> OnInitializeFailed: " + message); 386 | } 387 | } 388 | 389 | } 390 | 391 | #endif 392 | -------------------------------------------------------------------------------- /InputManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class InputManager : Singleton 6 | { 7 | [SerializeField] 8 | List Pressed = new List(); 9 | 10 | public float GetAxis(string name){ 11 | return Input.GetAxis(name); 12 | } 13 | 14 | public float GetAxisRaw(string name){ 15 | return Input.GetAxisRaw(name); 16 | } 17 | 18 | public bool GetAxisPressed(string name){ 19 | if(Pressed.IndexOf(name) >= 0){ 20 | if(Input.GetAxisRaw(name) == 0) 21 | Pressed.Remove(name); 22 | return false; 23 | } 24 | 25 | 26 | if(Input.GetAxisRaw(name) != 0){ 27 | Pressed.Add(name); 28 | return true; 29 | }else{ 30 | return false; 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /InvertMaskUI.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | using UnityEngine.Rendering; 6 | 7 | public class InvertMaskUI : Image 8 | { 9 | public override Material materialForRendering 10 | { 11 | get 12 | { 13 | Material material = new Material(base.materialForRendering); 14 | material.SetInt("_StencilComp", (int)CompareFunction.NotEqual); 15 | return material; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /JoyStick.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class JoyStick : Singleton 6 | { 7 | [SerializeField] 8 | Transform Root,Pad; 9 | [SerializeField] 10 | float MaxR = 1; 11 | 12 | Vector2 Origin = new Vector2(0,0); 13 | [SerializeField] 14 | bool _IsOriginSet = false; 15 | // Start is called before the first frame update 16 | void Start() 17 | { 18 | 19 | } 20 | 21 | // Update is called once per frame 22 | void Update() 23 | { 24 | ListenJoyStick(); 25 | ReleaseTouch(); 26 | } 27 | 28 | void ListenJoyStick(){ 29 | 30 | if(!Input.GetMouseButton(0)) 31 | return; 32 | if(!_IsOriginSet){ 33 | _IsOriginSet = true; 34 | Origin = Input.mousePosition; 35 | Root.position = Origin; 36 | Pad.transform.position = Origin; 37 | Root.gameObject.SetActive(true); 38 | return; 39 | } 40 | Vector2 currentTouch = (Vector2)Input.mousePosition-Origin; 41 | if(currentTouch == Vector2.zero) 42 | return; 43 | if(currentTouch.magnitude <= MaxR){ 44 | Pad.transform.position = Input.mousePosition; 45 | return; 46 | } 47 | 48 | float currentAngle = Mathf.Atan2(currentTouch.y,currentTouch.x); 49 | float X = Origin.x + MaxR * Mathf.Cos(currentAngle); 50 | float Y = Origin.y + MaxR * Mathf.Sin(currentAngle); 51 | Pad.transform.position = new Vector2(X,Y); 52 | } 53 | 54 | void ReleaseTouch(){ 55 | if(!_IsOriginSet) 56 | return; 57 | if(Input.GetMouseButtonUp(0)){ 58 | _IsOriginSet = false; 59 | Root.gameObject.SetActive(false); 60 | } 61 | } 62 | 63 | public Vector2 GetJoyVector(){ 64 | if(!_IsOriginSet) 65 | return Vector2.zero; 66 | Vector2 tmp = (Vector2)Input.mousePosition-Origin; 67 | return tmp.normalized; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /KDL.txt: -------------------------------------------------------------------------------- 1 | Number - Số nguyên 2, 3, 4,5 ... 2 | + -2^31 đến 2^31-1 (int) * 3 | + -2^63 đến 2^63-1 (long) 4 | - số thực 1.5, 3.6 .. 5 | + +/- 1.5 x 10^-45 đến +/-3.4 x 10^38 (float) * 6 | + +/- 1.0 x 10^-28 đến +/-7.9228 x 10^28 (double) 7 | Text - Chuỗi (string) "ITPlus" "I" "" 8 | - kí tự (char) 'H' 'I' '' 9 | 10 | 11 | Logic (bool) - true/false 12 | 13 | Cú pháp khai báo biến: 14 | 15 | (kiểu dữ liệu) (tên biến); 16 | 17 | (kiểu dữ liệu) (tên biến) = (giá trị); 18 | 19 | int A; (null) 20 | int A = 0; -------------------------------------------------------------------------------- /Laser.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhathuy7996/ReUseScript_Unity/4aa91d90bf757c82774baf3a3bb86d4ea2a514ef/Laser.unitypackage -------------------------------------------------------------------------------- /LazyPooling.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace HuynnLib{ 5 | public class LazyPooling : MonoBehaviour 6 | { 7 | 8 | private static LazyPooling _instant; 9 | public static LazyPooling Instant { 10 | get 11 | { 12 | if (_instant == null) 13 | { 14 | if (FindObjectOfType() != null) 15 | _instant = FindObjectOfType(); 16 | else 17 | new GameObject().AddComponent().name = "Singleton_"+ typeof(LazyPooling).ToString(); 18 | } 19 | 20 | return _instant; 21 | } 22 | } 23 | 24 | void Awake() 25 | { 26 | if (_instant != null && _instant.gameObject.GetInstanceID() != this.gameObject.GetInstanceID()) 27 | { 28 | Debug.LogError("Singleton already exist "+ _instant.gameObject.name); 29 | Destroy(this.gameObject); 30 | } 31 | else 32 | _instant = this.GetComponent(); 33 | } 34 | 35 | 36 | Dictionary> _poolObjects2 = new Dictionary>(); 37 | 38 | public GameObject GetObj(GameObject objKey, bool isKeepParent = false){ 39 | if (!_poolObjects2.ContainsKey(objKey)) 40 | { 41 | _poolObjects2.Add(objKey, new List()); 42 | } 43 | 44 | foreach (var g in _poolObjects2[objKey]) 45 | { 46 | if (g.gameObject.activeSelf) 47 | continue; 48 | return g; 49 | } 50 | 51 | GameObject g2 = Instantiate(objKey); 52 | _poolObjects2[objKey].Add(g2); 53 | 54 | if (isKeepParent) 55 | g2.transform.SetParent(objKey.transform.parent); 56 | return g2; 57 | } 58 | 59 | Dictionary> _poolObjt = new Dictionary>(); 60 | 61 | public T getObj(T objKey, bool isKeepParent = false) where T : Component 62 | { 63 | if (!_poolObjt.ContainsKey(objKey)) 64 | { 65 | _poolObjt.Add(objKey, new List()); 66 | } 67 | 68 | foreach (T g in _poolObjt[objKey]) 69 | { 70 | if (g.gameObject.activeSelf) 71 | continue; 72 | return g; 73 | } 74 | 75 | T g2 = Instantiate(objKey); 76 | _poolObjt[objKey].Add(g2); 77 | 78 | if (isKeepParent) 79 | g2.transform.SetParent(objKey.transform.parent); 80 | return g2; 81 | } 82 | 83 | public void resetObj( T objKey) where T:Component 84 | { 85 | if (!_poolObjt.ContainsKey(objKey)) 86 | { 87 | return; 88 | } 89 | 90 | foreach (T g in _poolObjt[objKey]) 91 | { 92 | g.gameObject.SetActive(false); 93 | } 94 | } 95 | 96 | 97 | 98 | public void CreatePool(T keyObj, int size) where T : Component 99 | { 100 | if (!_poolObjt.ContainsKey(keyObj)) 101 | { 102 | _poolObjt.Add(keyObj, new List()); 103 | } 104 | for (int i = 0; i < size; i++) 105 | { 106 | this.getObj(keyObj,true).gameObject.SetActive(false); 107 | } 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /MaterialExtensions.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | public static class MaterialExtensions 3 | { 4 | public static void ToOpaqueMode(this Material material) 5 | { 6 | material.SetOverrideTag("RenderType", ""); 7 | material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); 8 | material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); 9 | material.SetInt("_ZWrite", 1); 10 | material.DisableKeyword("_ALPHATEST_ON"); 11 | material.DisableKeyword("_ALPHABLEND_ON"); 12 | material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); 13 | material.renderQueue = -1; 14 | } 15 | 16 | public static void ToFadeMode(this Material material) 17 | { 18 | material.SetOverrideTag("RenderType", "Transparent"); 19 | material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); 20 | material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); 21 | material.SetInt("_ZWrite", 0); 22 | material.DisableKeyword("_ALPHATEST_ON"); 23 | material.EnableKeyword("_ALPHABLEND_ON"); 24 | material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); 25 | material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; 26 | } 27 | } -------------------------------------------------------------------------------- /Nice_Vibrations_Haptic_Feedback_for_Mobile_Gamepads_v3_9_unitypackage.file: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhathuy7996/ReUseScript_Unity/4aa91d90bf757c82774baf3a3bb86d4ea2a514ef/Nice_Vibrations_Haptic_Feedback_for_Mobile_Gamepads_v3_9_unitypackage.file -------------------------------------------------------------------------------- /NotiManager/IGameNotification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using UnityEngine; 6 | #if UNITY_IOS 7 | using Unity.Notifications.iOS; 8 | #else 9 | using Unity.Notifications.Android; 10 | #endif 11 | using UnityEngine.Assertions; 12 | 13 | /// 14 | /// Represents a notification that will be delivered for this application. 15 | /// 16 | public interface IGameNotification 17 | { 18 | /// 19 | /// Gets or sets a unique identifier for this notification. 20 | /// 21 | /// 22 | /// 23 | /// If null, will be generated automatically once the notification is delivered, and then 24 | /// can be retrieved afterwards. 25 | /// 26 | /// On some platforms, this might be converted to a string identifier internally. 27 | /// 28 | /// A unique integer identifier for this notification, or null (on some platforms) if not explicitly set. 29 | int? Id { get; set; } 30 | 31 | /// 32 | /// Gets or sets the notification's title. 33 | /// 34 | /// The title message for the notification. 35 | string Title { get; set; } 36 | 37 | /// 38 | /// Gets or sets the body text of the notification. 39 | /// 40 | /// The body message for the notification. 41 | string Body { get; set; } 42 | 43 | /// 44 | /// Gets or sets a subtitle for the notification. 45 | /// 46 | /// The subtitle message for the notification. 47 | string Subtitle { get; set; } 48 | 49 | /// 50 | /// Gets or sets optional arbitrary data for the notification. 51 | /// 52 | string Data { get; set; } 53 | 54 | /// 55 | /// Gets or sets group to which this notification belongs. 56 | /// 57 | /// A platform specific string identifier for the notification's group. 58 | string Group { get; set; } 59 | 60 | /// 61 | /// Gets or sets the badge number for this notification. No badge number will be shown if null. 62 | /// 63 | /// The number displayed on the app badge. 64 | int? BadgeNumber { get; set; } 65 | 66 | /// 67 | /// Gets or sets if this notification will be dismissed automatically when the user taps it. 68 | /// Only available on Android. 69 | /// 70 | bool ShouldAutoCancel { get; set; } 71 | 72 | /// 73 | /// Gets or sets time to deliver the notification. 74 | /// 75 | /// The time of delivery in local time. 76 | DateTime? DeliveryTime { get; set; } 77 | 78 | /// 79 | /// Gets whether this notification has been scheduled. 80 | /// 81 | /// True if the notification has been scheduled with the underlying operating system. 82 | bool Scheduled { get; } 83 | 84 | /// 85 | /// Notification small icon. 86 | /// 87 | string SmallIcon { get; set; } 88 | 89 | /// 90 | /// Notification large icon. 91 | /// 92 | string LargeIcon { get; set; } 93 | } 94 | public interface IGameNotificationsPlatform 95 | { 96 | /// 97 | /// Fired when a notification is received. 98 | /// 99 | event Action NotificationReceived; 100 | 101 | /// 102 | /// Create a new instance of a for this platform. 103 | /// 104 | /// A new platform-appropriate notification object. 105 | IGameNotification CreateNotification(); 106 | 107 | /// 108 | /// Schedules a notification to be delivered. 109 | /// 110 | /// The notification to deliver. 111 | /// is null. 112 | /// isn't of the correct type. 113 | void ScheduleNotification(IGameNotification gameNotification); 114 | 115 | /// 116 | /// Cancels a scheduled notification. 117 | /// 118 | /// The ID of a previously scheduled notification. 119 | void CancelNotification(int notificationId); 120 | 121 | /// 122 | /// Dismiss a displayed notification. 123 | /// 124 | /// The ID of a previously scheduled notification that is being displayed to the user. 125 | void DismissNotification(int notificationId); 126 | 127 | /// 128 | /// Cancels all scheduled notifications. 129 | /// 130 | void CancelAllScheduledNotifications(); 131 | 132 | /// 133 | /// Dismisses all displayed notifications. 134 | /// 135 | void DismissAllDisplayedNotifications(); 136 | 137 | /// 138 | /// Use this to retrieve the last local or remote notification received by the app. 139 | /// 140 | /// 141 | /// On Android the last notification is not cleared until the application is explicitly quit. 142 | /// 143 | /// 144 | /// Returns the last local or remote notification used to open the app or clicked on by the user. If no 145 | /// notification is available it returns null. 146 | /// 147 | IGameNotification GetLastNotification(); 148 | 149 | /// 150 | /// Performs any initialization or processing necessary on foregrounding the application. 151 | /// 152 | void OnForeground(); 153 | 154 | /// 155 | /// Performs any processing necessary on backgrounding or closing the application. 156 | /// 157 | void OnBackground(); 158 | } 159 | 160 | /// 161 | /// Any type that handles notifications for a specific game platform. 162 | /// 163 | /// Has a concrete notification type 164 | /// The type of notification returned by this platform. 165 | public interface IGameNotificationsPlatform : IGameNotificationsPlatform 166 | where TNotificationType : IGameNotification 167 | { 168 | /// 169 | /// Create an instance of . 170 | /// 171 | /// A new platform-appropriate notification object. 172 | new TNotificationType CreateNotification(); 173 | 174 | /// 175 | /// Schedule a notification to be delivered. 176 | /// 177 | /// The notification to deliver. 178 | /// is null. 179 | void ScheduleNotification(TNotificationType notification); 180 | 181 | /// 182 | /// Use this to retrieve the last local or remote notification of 183 | /// received by the app. 184 | /// 185 | /// 186 | /// On Android the last notification is not cleared until the application is explicitly quit. 187 | /// 188 | /// 189 | /// Returns new platform-appropriate notification object for the last local or remote notification used to open 190 | /// the app or clicked on by the user. If no notification is available it returns null. 191 | /// 192 | new TNotificationType GetLastNotification(); 193 | } 194 | 195 | public struct GameNotificationChannel 196 | { 197 | /// 198 | /// The style of notification shown for this channel. Corresponds to the Importance setting of 199 | /// an Android notification, and do nothing on iOS. 200 | /// 201 | public enum NotificationStyle 202 | { 203 | /// 204 | /// Notification does not appear in the status bar. 205 | /// 206 | None = 0, 207 | /// 208 | /// Notification makes no sound. 209 | /// 210 | NoSound = 2, 211 | /// 212 | /// Notification plays sound. 213 | /// 214 | Default = 3, 215 | /// 216 | /// Notification also displays a heads-up popup. 217 | /// 218 | Popup = 4 219 | } 220 | 221 | /// 222 | /// Controls how notifications display on the device lock screen. 223 | /// 224 | public enum PrivacyMode 225 | { 226 | /// 227 | /// Notifications aren't shown on secure lock screens. 228 | /// 229 | Secret = -1, 230 | /// 231 | /// Notifications display an icon, but content is concealed on secure lock screens. 232 | /// 233 | Private = 0, 234 | /// 235 | /// Notifications display on all lock screens. 236 | /// 237 | Public 238 | } 239 | 240 | /// 241 | /// The identifier for the channel. 242 | /// 243 | public readonly string Id; 244 | 245 | /// 246 | /// The name of the channel as displayed to the user. 247 | /// 248 | public readonly string Name; 249 | 250 | /// 251 | /// The description of the channel as displayed to the user. 252 | /// 253 | public readonly string Description; 254 | 255 | /// 256 | /// A flag determining whether messages on this channel can show a badge. Defaults to true. 257 | /// 258 | public readonly bool ShowsBadge; 259 | 260 | /// 261 | /// A flag determining whether messages on this channel cause the device light to flash. Defaults to false. 262 | /// 263 | public readonly bool ShowLights; 264 | 265 | /// 266 | /// A flag determining whether messages on this channel cause the device to vibrate. Defaults to true. 267 | /// 268 | public readonly bool Vibrates; 269 | 270 | /// 271 | /// A flag determining whether messages on this channel bypass do not disturb settings. Defaults to false. 272 | /// 273 | public readonly bool HighPriority; 274 | 275 | /// 276 | /// The display style for this notification. Defaults to . 277 | /// 278 | public readonly NotificationStyle Style; 279 | 280 | /// 281 | /// The privacy setting for this notification. Defaults to . 282 | /// 283 | public readonly PrivacyMode Privacy; 284 | 285 | /// 286 | /// The custom vibration pattern for this channel. Set to null to use the default. 287 | /// 288 | public readonly int[] VibrationPattern; 289 | 290 | /// 291 | /// Initialize a new instance of with 292 | /// optional fields set to their default values. 293 | /// 294 | public GameNotificationChannel(string id, string name, string description) : this() 295 | { 296 | Id = id; 297 | Name = name; 298 | Description = description; 299 | 300 | ShowsBadge = true; 301 | ShowLights = false; 302 | Vibrates = true; 303 | HighPriority = false; 304 | Style = NotificationStyle.Popup; 305 | Privacy = PrivacyMode.Public; 306 | VibrationPattern = null; 307 | } 308 | 309 | /// 310 | /// Initialize a new instance of , providing the notification style 311 | /// and optionally all other settings. 312 | /// 313 | public GameNotificationChannel(string id, string name, string description, NotificationStyle style, bool showsBadge = true, bool showLights = false, bool vibrates = true, bool highPriority = false, PrivacyMode privacy = PrivacyMode.Public, long[] vibrationPattern = null) 314 | { 315 | Id = id; 316 | Name = name; 317 | Description = description; 318 | ShowsBadge = showsBadge; 319 | ShowLights = showLights; 320 | Vibrates = vibrates; 321 | HighPriority = highPriority; 322 | Style = style; 323 | Privacy = privacy; 324 | if (vibrationPattern != null) 325 | VibrationPattern = vibrationPattern.Select(v => (int)v).ToArray(); 326 | else 327 | VibrationPattern = null; 328 | } 329 | } 330 | 331 | public interface IPendingNotificationsSerializer 332 | { 333 | /// 334 | /// Save a list of pending notifications. 335 | /// 336 | /// The collection notifications to save. 337 | void Serialize(IList notifications); 338 | 339 | /// 340 | /// Retrieve a saved list of pending notifications. 341 | /// 342 | /// The deserialized collection of pending notifications, or null if the file did not exist. 343 | IList Deserialize(IGameNotificationsPlatform platform); 344 | } 345 | 346 | public class PendingNotification 347 | { 348 | /// 349 | /// Whether to reschedule this event if it hasn't displayed once the app is foregrounded again. 350 | /// 351 | /// 352 | /// 353 | /// Only valid if the 's 354 | /// flag is set to . 355 | /// 356 | /// 357 | /// Will not function for any notifications that are using a delivery scheduling method that isn't time 358 | /// based, such as iOS location notifications. 359 | /// 360 | /// 361 | public bool Reschedule; 362 | 363 | /// 364 | /// The scheduled notification. 365 | /// 366 | public readonly IGameNotification Notification; 367 | 368 | /// 369 | /// Instantiate a new instance of from a . 370 | /// 371 | /// The notification to create from. 372 | public PendingNotification(IGameNotification notification) 373 | { 374 | Notification = notification ?? throw new ArgumentNullException(nameof(notification)); 375 | } 376 | } 377 | 378 | public class DefaultSerializer : IPendingNotificationsSerializer 379 | { 380 | private const byte Version = 1; 381 | 382 | private readonly string filename; 383 | 384 | /// 385 | /// Instantiate a new instance of . 386 | /// 387 | /// The filename to save to. This should be an absolute path. 388 | public DefaultSerializer(string filename) 389 | { 390 | this.filename = filename; 391 | } 392 | 393 | /// 394 | public void Serialize(IList notifications) 395 | { 396 | using (var file = new FileStream(filename, FileMode.Create)) 397 | { 398 | using (var writer = new BinaryWriter(file)) 399 | { 400 | // Write version number 401 | writer.Write(Version); 402 | 403 | // Write list length 404 | writer.Write(notifications.Count); 405 | 406 | // Write each item 407 | foreach (PendingNotification notificationToSave in notifications) 408 | { 409 | IGameNotification notification = notificationToSave.Notification; 410 | 411 | // ID 412 | writer.Write(notification.Id.HasValue); 413 | if (notification.Id.HasValue) 414 | { 415 | writer.Write(notification.Id.Value); 416 | } 417 | 418 | // Title 419 | writer.Write(notification.Title ?? ""); 420 | 421 | // Body 422 | writer.Write(notification.Body ?? ""); 423 | 424 | // Subtitle 425 | writer.Write(notification.Subtitle ?? ""); 426 | 427 | // Group 428 | writer.Write(notification.Group ?? ""); 429 | 430 | // Data 431 | writer.Write(notification.Data ?? ""); 432 | 433 | // Badge 434 | writer.Write(notification.BadgeNumber.HasValue); 435 | if (notification.BadgeNumber.HasValue) 436 | { 437 | writer.Write(notification.BadgeNumber.Value); 438 | } 439 | 440 | // Time (must have a value) 441 | writer.Write(notification.DeliveryTime.Value.Ticks); 442 | } 443 | } 444 | } 445 | } 446 | 447 | /// 448 | public IList Deserialize(IGameNotificationsPlatform platform) 449 | { 450 | if (!File.Exists(filename)) 451 | { 452 | return null; 453 | } 454 | 455 | using (var file = new FileStream(filename, FileMode.Open)) 456 | { 457 | using (var reader = new BinaryReader(file)) 458 | { 459 | // Version 460 | var version = reader.ReadByte(); 461 | 462 | // Length 463 | int numElements = reader.ReadInt32(); 464 | 465 | var result = new List(numElements); 466 | for (var i = 0; i < numElements; ++i) 467 | { 468 | IGameNotification notification = platform.CreateNotification(); 469 | bool hasValue; 470 | 471 | // ID 472 | hasValue = reader.ReadBoolean(); 473 | if (hasValue) 474 | { 475 | notification.Id = reader.ReadInt32(); 476 | } 477 | 478 | // Title 479 | notification.Title = reader.ReadString(); 480 | 481 | // Body 482 | notification.Body = reader.ReadString(); 483 | 484 | // Body 485 | notification.Subtitle = reader.ReadString(); 486 | 487 | // Group 488 | notification.Group = reader.ReadString(); 489 | 490 | // Data, introduced in version 1 491 | if (version > 0) 492 | notification.Data = reader.ReadString(); 493 | 494 | // Badge 495 | hasValue = reader.ReadBoolean(); 496 | if (hasValue) 497 | { 498 | notification.BadgeNumber = reader.ReadInt32(); 499 | } 500 | 501 | // Time 502 | notification.DeliveryTime = new DateTime(reader.ReadInt64(), DateTimeKind.Local); 503 | 504 | result.Add(notification); 505 | } 506 | 507 | return result; 508 | } 509 | } 510 | } 511 | } 512 | 513 | 514 | #if UNITY_IOS 515 | public class iOSGameNotification : IGameNotification 516 | { 517 | private readonly iOSNotification internalNotification; 518 | 519 | /// 520 | /// Gets the internal notification object used by the mobile notifications system. 521 | /// 522 | public iOSNotification InternalNotification => internalNotification; 523 | 524 | /// 525 | /// 526 | /// Internally stored as a string. Gets parsed to an integer when retrieving. 527 | /// 528 | /// The identifier as an integer, or null if the identifier couldn't be parsed as a number. 529 | public int? Id 530 | { 531 | get 532 | { 533 | if (!int.TryParse(internalNotification.Identifier, out int value)) 534 | { 535 | Debug.LogWarning("Internal iOS notification's identifier isn't a number."); 536 | return null; 537 | } 538 | 539 | return value; 540 | } 541 | set 542 | { 543 | if (value == null) 544 | { 545 | throw new ArgumentNullException(nameof(value)); 546 | } 547 | 548 | internalNotification.Identifier = value.Value.ToString(); 549 | } 550 | } 551 | 552 | /// 553 | public string Title { get => internalNotification.Title; set => internalNotification.Title = value; } 554 | 555 | /// 556 | public string Body { get => internalNotification.Body; set => internalNotification.Body = value; } 557 | 558 | /// 559 | public string Subtitle { get => internalNotification.Subtitle; set => internalNotification.Subtitle = value; } 560 | 561 | /// 562 | public string Data { get => internalNotification.Data; set => internalNotification.Data = value; } 563 | 564 | /// 565 | /// 566 | /// On iOS, this represents the notification's Category Identifier. 567 | /// 568 | /// The value of . 569 | public string Group { get => CategoryIdentifier; set => CategoryIdentifier = value; } 570 | 571 | /// 572 | public int? BadgeNumber 573 | { 574 | get => internalNotification.Badge != -1 ? internalNotification.Badge : (int?)null; 575 | set => internalNotification.Badge = value ?? -1; 576 | } 577 | 578 | /// 579 | public bool ShouldAutoCancel { get; set; } 580 | 581 | /// 582 | public bool Scheduled { get; private set; } 583 | 584 | /// 585 | /// 586 | /// On iOS, setting this causes the notification to be delivered on a calendar time. 587 | /// If it has previously been manually set to a different type of trigger, or has not been set before, 588 | /// this returns null. 589 | /// The millisecond component of the provided DateTime is ignored. 590 | /// 591 | /// A representing the delivery time of this message, or null if 592 | /// not set or the trigger isn't a . 593 | public DateTime? DeliveryTime 594 | { 595 | get 596 | { 597 | if (!(internalNotification.Trigger is iOSNotificationCalendarTrigger calendarTrigger)) 598 | { 599 | return null; 600 | } 601 | 602 | DateTime now = DateTime.Now; 603 | var result = new DateTime 604 | ( 605 | calendarTrigger.Year ?? now.Year, 606 | calendarTrigger.Month ?? now.Month, 607 | calendarTrigger.Day ?? now.Day, 608 | calendarTrigger.Hour ?? now.Hour, 609 | calendarTrigger.Minute ?? now.Minute, 610 | calendarTrigger.Second ?? now.Second, 611 | DateTimeKind.Local 612 | ); 613 | 614 | return result; 615 | } 616 | set 617 | { 618 | if (!value.HasValue) 619 | { 620 | return; 621 | } 622 | 623 | DateTime date = value.Value.ToLocalTime(); 624 | 625 | internalNotification.Trigger = new iOSNotificationCalendarTrigger 626 | { 627 | Year = date.Year, 628 | Month = date.Month, 629 | Day = date.Day, 630 | Hour = date.Hour, 631 | Minute = date.Minute, 632 | Second = date.Second 633 | }; 634 | } 635 | } 636 | 637 | /// 638 | /// The category identifier for this notification. 639 | /// 640 | public string CategoryIdentifier 641 | { 642 | get => internalNotification.CategoryIdentifier; 643 | set => internalNotification.CategoryIdentifier = value; 644 | } 645 | 646 | /// 647 | /// Does nothing on iOS. 648 | /// 649 | public string SmallIcon { get => null; set { } } 650 | 651 | /// 652 | /// Does nothing on iOS. 653 | /// 654 | public string LargeIcon { get => null; set { } } 655 | 656 | /// 657 | /// Instantiate a new instance of . 658 | /// 659 | public iOSGameNotification() 660 | { 661 | internalNotification = new iOSNotification 662 | { 663 | ShowInForeground = true // Deliver in foreground by default 664 | }; 665 | } 666 | 667 | /// 668 | /// Instantiate a new instance of from a delivered notification. 669 | /// 670 | /// The delivered notification. 671 | internal iOSGameNotification(iOSNotification internalNotification) 672 | { 673 | this.internalNotification = internalNotification; 674 | } 675 | 676 | /// 677 | /// Mark this notifications scheduled flag. 678 | /// 679 | internal void OnScheduled() 680 | { 681 | Assert.IsFalse(Scheduled); 682 | Scheduled = true; 683 | } 684 | } 685 | 686 | /// 687 | /// iOS implementation of . 688 | /// 689 | public class iOSNotificationsPlatform : IGameNotificationsPlatform, 690 | IDisposable 691 | { 692 | /// 693 | public event Action NotificationReceived; 694 | 695 | /// 696 | /// Instantiate a new instance of . 697 | /// 698 | public iOSNotificationsPlatform() 699 | { 700 | iOSNotificationCenter.OnNotificationReceived += OnLocalNotificationReceived; 701 | } 702 | 703 | /// 704 | public void ScheduleNotification(IGameNotification gameNotification) 705 | { 706 | if (gameNotification == null) 707 | { 708 | throw new ArgumentNullException(nameof(gameNotification)); 709 | } 710 | 711 | if (!(gameNotification is iOSGameNotification notification)) 712 | { 713 | throw new InvalidOperationException( 714 | "Notification provided to ScheduleNotification isn't an iOSGameNotification."); 715 | } 716 | 717 | ScheduleNotification(notification); 718 | } 719 | 720 | /// 721 | public void ScheduleNotification(iOSGameNotification notification) 722 | { 723 | if (notification == null) 724 | { 725 | throw new ArgumentNullException(nameof(notification)); 726 | } 727 | 728 | iOSNotificationCenter.ScheduleNotification(notification.InternalNotification); 729 | notification.OnScheduled(); 730 | } 731 | 732 | /// 733 | /// 734 | /// Create a new . 735 | /// 736 | IGameNotification IGameNotificationsPlatform.CreateNotification() 737 | { 738 | return CreateNotification(); 739 | } 740 | 741 | /// 742 | /// 743 | /// Create a new . 744 | /// 745 | public iOSGameNotification CreateNotification() 746 | { 747 | return new iOSGameNotification(); 748 | } 749 | 750 | /// 751 | public void CancelNotification(int notificationId) 752 | { 753 | iOSNotificationCenter.RemoveScheduledNotification(notificationId.ToString()); 754 | } 755 | 756 | /// 757 | public void DismissNotification(int notificationId) 758 | { 759 | iOSNotificationCenter.RemoveDeliveredNotification(notificationId.ToString()); 760 | } 761 | 762 | /// 763 | public void CancelAllScheduledNotifications() 764 | { 765 | iOSNotificationCenter.RemoveAllScheduledNotifications(); 766 | } 767 | 768 | /// 769 | public void DismissAllDisplayedNotifications() 770 | { 771 | iOSNotificationCenter.RemoveAllDeliveredNotifications(); 772 | } 773 | 774 | /// 775 | IGameNotification IGameNotificationsPlatform.GetLastNotification() 776 | { 777 | return GetLastNotification(); 778 | } 779 | 780 | /// 781 | public iOSGameNotification GetLastNotification() 782 | { 783 | var notification = iOSNotificationCenter.GetLastRespondedNotification(); 784 | 785 | if (notification != null) 786 | { 787 | return new iOSGameNotification(notification); 788 | } 789 | 790 | return null; 791 | } 792 | 793 | /// 794 | /// Clears badge count. 795 | /// 796 | public void OnForeground() 797 | { 798 | iOSNotificationCenter.ApplicationBadge = 0; 799 | } 800 | 801 | /// 802 | /// Does nothing on iOS. 803 | /// 804 | public void OnBackground() { } 805 | 806 | /// 807 | /// Unregister delegates. 808 | /// 809 | public void Dispose() 810 | { 811 | iOSNotificationCenter.OnNotificationReceived -= OnLocalNotificationReceived; 812 | } 813 | 814 | // Event handler for receiving local notifications. 815 | private void OnLocalNotificationReceived(iOSNotification notification) 816 | { 817 | // Create a new AndroidGameNotification out of the delivered notification, but only 818 | // if the event is registered 819 | NotificationReceived?.Invoke(new iOSGameNotification(notification)); 820 | } 821 | } 822 | #else 823 | public class AndroidNotificationsPlatform : IGameNotificationsPlatform, 824 | IDisposable 825 | { 826 | /// 827 | public event Action NotificationReceived; 828 | 829 | /// 830 | /// Gets or sets the default channel ID for notifications. 831 | /// 832 | /// The default channel ID for new notifications, or null. 833 | public string DefaultChannelId { get; set; } 834 | 835 | /// 836 | /// Instantiate a new instance of . 837 | /// 838 | public AndroidNotificationsPlatform() 839 | { 840 | AndroidNotificationCenter.OnNotificationReceived += OnLocalNotificationReceived; 841 | } 842 | 843 | /// 844 | /// 845 | /// Will set the field of . 846 | /// 847 | public void ScheduleNotification(AndroidGameNotification gameNotification) 848 | { 849 | if (gameNotification == null) 850 | { 851 | throw new ArgumentNullException(nameof(gameNotification)); 852 | } 853 | 854 | if (gameNotification.Id.HasValue) 855 | { 856 | AndroidNotificationCenter.SendNotificationWithExplicitID(gameNotification.InternalNotification, 857 | gameNotification.DeliveredChannel, 858 | gameNotification.Id.Value); 859 | } 860 | else 861 | { 862 | int notificationId = AndroidNotificationCenter.SendNotification(gameNotification.InternalNotification, 863 | gameNotification.DeliveredChannel); 864 | gameNotification.Id = notificationId; 865 | } 866 | 867 | gameNotification.OnScheduled(); 868 | } 869 | 870 | /// 871 | /// 872 | /// Will set the field of . 873 | /// 874 | public void ScheduleNotification(IGameNotification gameNotification) 875 | { 876 | if (gameNotification == null) 877 | { 878 | throw new ArgumentNullException(nameof(gameNotification)); 879 | } 880 | 881 | if (!(gameNotification is AndroidGameNotification androidNotification)) 882 | { 883 | throw new InvalidOperationException( 884 | "Notification provided to ScheduleNotification isn't an AndroidGameNotification."); 885 | } 886 | 887 | ScheduleNotification(androidNotification); 888 | } 889 | 890 | /// 891 | /// 892 | /// Create a new . 893 | /// 894 | public AndroidGameNotification CreateNotification() 895 | { 896 | var notification = new AndroidGameNotification() 897 | { 898 | DeliveredChannel = DefaultChannelId 899 | }; 900 | 901 | return notification; 902 | } 903 | 904 | /// 905 | /// 906 | /// Create a new . 907 | /// 908 | IGameNotification IGameNotificationsPlatform.CreateNotification() 909 | { 910 | return CreateNotification(); 911 | } 912 | 913 | /// 914 | public void CancelNotification(int notificationId) 915 | { 916 | AndroidNotificationCenter.CancelScheduledNotification(notificationId); 917 | } 918 | 919 | /// 920 | /// 921 | /// Not currently implemented on Android 922 | /// 923 | public void DismissNotification(int notificationId) 924 | { 925 | AndroidNotificationCenter.CancelDisplayedNotification(notificationId); 926 | } 927 | 928 | /// 929 | public void CancelAllScheduledNotifications() 930 | { 931 | AndroidNotificationCenter.CancelAllScheduledNotifications(); 932 | } 933 | 934 | /// 935 | public void DismissAllDisplayedNotifications() 936 | { 937 | AndroidNotificationCenter.CancelAllDisplayedNotifications(); 938 | } 939 | 940 | /// 941 | IGameNotification IGameNotificationsPlatform.GetLastNotification() 942 | { 943 | return GetLastNotification(); 944 | } 945 | 946 | /// 947 | public AndroidGameNotification GetLastNotification() 948 | { 949 | var data = AndroidNotificationCenter.GetLastNotificationIntent(); 950 | 951 | if (data != null) 952 | { 953 | return new AndroidGameNotification(data.Notification, data.Id, data.Channel); 954 | } 955 | 956 | return null; 957 | } 958 | 959 | /// 960 | /// Does nothing on Android. 961 | /// 962 | public void OnForeground() { } 963 | 964 | /// 965 | /// Does nothing on Android. 966 | /// 967 | public void OnBackground() { } 968 | 969 | /// 970 | /// Unregister delegates. 971 | /// 972 | public void Dispose() 973 | { 974 | AndroidNotificationCenter.OnNotificationReceived -= OnLocalNotificationReceived; 975 | } 976 | 977 | // Event handler for receiving local notifications. 978 | private void OnLocalNotificationReceived(AndroidNotificationIntentData data) 979 | { 980 | // Create a new AndroidGameNotification out of the delivered notification, but only 981 | // if the event is registered 982 | NotificationReceived?.Invoke(new AndroidGameNotification(data.Notification, data.Id, data.Channel)); 983 | } 984 | } 985 | 986 | public class AndroidGameNotification : IGameNotification 987 | { 988 | private AndroidNotification internalNotification; 989 | 990 | /// 991 | /// Gets the internal notification object used by the mobile notifications system. 992 | /// 993 | public AndroidNotification InternalNotification => internalNotification; 994 | 995 | /// 996 | /// 997 | /// On Android, if the ID isn't explicitly set, it will be generated after it has been scheduled. 998 | /// 999 | public int? Id { get; set; } 1000 | 1001 | /// 1002 | public string Title { get => InternalNotification.Title; set => internalNotification.Title = value; } 1003 | 1004 | /// 1005 | public string Body { get => InternalNotification.Text; set => internalNotification.Text = value; } 1006 | 1007 | /// 1008 | /// Does nothing on Android. 1009 | /// 1010 | public string Subtitle { get => null; set { } } 1011 | 1012 | /// 1013 | public string Data { get => InternalNotification.IntentData; set => internalNotification.IntentData = value; } 1014 | 1015 | /// 1016 | /// 1017 | /// On Android, this represents the notification's channel, and is required. Will be configured automatically by 1018 | /// if is set 1019 | /// 1020 | /// The value of . 1021 | public string Group { get => DeliveredChannel; set => DeliveredChannel = value; } 1022 | 1023 | /// 1024 | public int? BadgeNumber 1025 | { 1026 | get => internalNotification.Number != -1 ? internalNotification.Number : (int?)null; 1027 | set => internalNotification.Number = value ?? -1; 1028 | } 1029 | 1030 | /// 1031 | public bool ShouldAutoCancel 1032 | { 1033 | get => InternalNotification.ShouldAutoCancel; 1034 | set => internalNotification.ShouldAutoCancel = value; 1035 | } 1036 | 1037 | /// 1038 | public DateTime? DeliveryTime 1039 | { 1040 | get => InternalNotification.FireTime; 1041 | set => internalNotification.FireTime = value ?? throw new ArgumentNullException(nameof(value)); 1042 | } 1043 | 1044 | /// 1045 | /// Gets or sets the channel for this notification. 1046 | /// 1047 | public string DeliveredChannel { get; set; } 1048 | 1049 | /// 1050 | public bool Scheduled { get; private set; } 1051 | 1052 | /// 1053 | public string SmallIcon { get => InternalNotification.SmallIcon; set => internalNotification.SmallIcon = value; } 1054 | 1055 | /// 1056 | public string LargeIcon { get => InternalNotification.LargeIcon; set => internalNotification.LargeIcon = value; } 1057 | 1058 | /// 1059 | /// Instantiate a new instance of . 1060 | /// 1061 | public AndroidGameNotification() 1062 | { 1063 | internalNotification = new AndroidNotification(); 1064 | } 1065 | 1066 | /// 1067 | /// Instantiate a new instance of from a delivered notification 1068 | /// 1069 | /// The notification that has been delivered. 1070 | /// The ID of the delivered notification. 1071 | /// The channel the notification was delivered to. 1072 | internal AndroidGameNotification(AndroidNotification deliveredNotification, int deliveredId, 1073 | string deliveredChannel) 1074 | { 1075 | internalNotification = deliveredNotification; 1076 | Id = deliveredId; 1077 | DeliveredChannel = deliveredChannel; 1078 | } 1079 | 1080 | /// 1081 | /// Set the scheduled flag. 1082 | /// 1083 | internal void OnScheduled() 1084 | { 1085 | Assert.IsFalse(Scheduled); 1086 | Scheduled = true; 1087 | } 1088 | } 1089 | 1090 | 1091 | #endif 1092 | -------------------------------------------------------------------------------- /NotiManager/NotiManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using UnityEngine; 6 | using Unity.Notifications.Android; 7 | using System.Linq; 8 | 9 | public class NotiManager : MonoBehaviour 10 | { 11 | private bool inForeground; 12 | 13 | public IGameNotificationsPlatform Platform { get; private set; } 14 | public bool Initialized { get; private set; } 15 | public List PendingNotifications { get; private set; } 16 | public IPendingNotificationsSerializer Serializer { get; set; } 17 | public event Action LocalNotificationDelivered; 18 | 19 | private const string DefaultFilename = "notifications.bin"; 20 | 21 | public const string ChannelId = "game_channel0"; 22 | public const string ReminderChannelId = "reminder_channel1"; 23 | public const string NewsChannelId = "news_channel2"; 24 | 25 | private bool updatePendingNotifications; 26 | 27 | 28 | 29 | // Start is called before the first frame update 30 | void Start() 31 | { 32 | var c1 = new GameNotificationChannel(ChannelId, "Default Game Channel", "Generic notifications"); 33 | var c2 = new GameNotificationChannel(NewsChannelId, "News Channel", "News feed notifications"); 34 | var c3 = new GameNotificationChannel(ReminderChannelId, "Reminder Channel", "Reminder notifications"); 35 | 36 | this.Initialize(c1, c2, c3); 37 | } 38 | 39 | // Update is called once per frame 40 | void Update() 41 | { 42 | 43 | } 44 | 45 | /// 46 | /// Initialize the notifications manager. 47 | /// 48 | /// An optional collection of channels to register, for Android 49 | /// has already been called. 50 | public void Initialize(params GameNotificationChannel[] channels) 51 | { 52 | if (Initialized) 53 | { 54 | throw new InvalidOperationException("NotificationsManager already initialized."); 55 | } 56 | 57 | Initialized = true; 58 | 59 | #if UNITY_ANDROID 60 | Platform = new AndroidNotificationsPlatform(); 61 | 62 | // Register the notification channels 63 | var doneDefault = false; 64 | foreach (GameNotificationChannel notificationChannel in channels) 65 | { 66 | if (!doneDefault) 67 | { 68 | doneDefault = true; 69 | ((AndroidNotificationsPlatform)Platform).DefaultChannelId = notificationChannel.Id; 70 | } 71 | 72 | long[] vibrationPattern = null; 73 | if (notificationChannel.VibrationPattern != null) 74 | vibrationPattern = notificationChannel.VibrationPattern.Select(v => (long)v).ToArray(); 75 | 76 | // Wrap channel in Android object 77 | var androidChannel = new AndroidNotificationChannel(notificationChannel.Id, notificationChannel.Name, 78 | notificationChannel.Description, 79 | (Importance)notificationChannel.Style) 80 | { 81 | CanBypassDnd = notificationChannel.HighPriority, 82 | CanShowBadge = notificationChannel.ShowsBadge, 83 | EnableLights = notificationChannel.ShowLights, 84 | EnableVibration = notificationChannel.Vibrates, 85 | LockScreenVisibility = (LockScreenVisibility)notificationChannel.Privacy, 86 | VibrationPattern = vibrationPattern 87 | }; 88 | 89 | AndroidNotificationCenter.RegisterNotificationChannel(androidChannel); 90 | } 91 | #elif UNITY_IOS 92 | Platform = new iOSNotificationsPlatform(); 93 | #endif 94 | 95 | if (Platform == null) 96 | { 97 | return; 98 | } 99 | 100 | PendingNotifications = new List(); 101 | Platform.NotificationReceived += OnNotificationReceived; 102 | 103 | // Check serializer 104 | if (Serializer == null) 105 | { 106 | Serializer = new DefaultSerializer(Path.Combine(Application.persistentDataPath, DefaultFilename)); 107 | } 108 | 109 | OnForegrounding(); 110 | } 111 | 112 | 113 | public void SendNotification(string title, string body, DateTime deliveryTime, int? badgeNumber = null, 114 | bool reschedule = false, string channelId = null, 115 | string smallIcon = null, string largeIcon = null) 116 | { 117 | IGameNotification notification = Platform?.CreateNotification(); 118 | 119 | if (notification == null) 120 | { 121 | return; 122 | } 123 | 124 | notification.Title = title; 125 | notification.Body = body; 126 | notification.Group = !string.IsNullOrEmpty(channelId) ? channelId : ChannelId; 127 | notification.DeliveryTime = deliveryTime; 128 | notification.SmallIcon = smallIcon; 129 | notification.LargeIcon = largeIcon; 130 | if (badgeNumber != null) 131 | { 132 | notification.BadgeNumber = badgeNumber; 133 | } 134 | 135 | PendingNotification notificationToDisplay = this.ScheduleNotification(notification); 136 | notificationToDisplay.Reschedule = reschedule; 137 | updatePendingNotifications = true; 138 | 139 | 140 | } 141 | 142 | /// 143 | /// Schedules a notification to be delivered. 144 | /// 145 | /// The notification to deliver. 146 | public PendingNotification ScheduleNotification(IGameNotification notification) 147 | { 148 | if (!Initialized) 149 | { 150 | throw new InvalidOperationException("Must call Initialize() first."); 151 | } 152 | 153 | if (notification == null || Platform == null) 154 | { 155 | return null; 156 | } 157 | 158 | Platform.ScheduleNotification(notification); 159 | 160 | // Register pending notification 161 | var result = new PendingNotification(notification); 162 | PendingNotifications.Add(result); 163 | 164 | return result; 165 | } 166 | 167 | 168 | /// 169 | /// Event fired by when a notification is received. 170 | /// 171 | private void OnNotificationReceived(IGameNotification deliveredNotification) 172 | { 173 | // Ignore for background messages (this happens on Android sometimes) 174 | if (!inForeground) 175 | { 176 | return; 177 | } 178 | 179 | // Find in pending list 180 | int deliveredIndex = 181 | PendingNotifications.FindIndex(scheduledNotification => 182 | scheduledNotification.Notification.Id == deliveredNotification.Id); 183 | if (deliveredIndex >= 0) 184 | { 185 | LocalNotificationDelivered?.Invoke(PendingNotifications[deliveredIndex]); 186 | 187 | PendingNotifications.RemoveAt(deliveredIndex); 188 | } 189 | } 190 | // Clear foreground notifications and reschedule stuff from a file 191 | private void OnForegrounding() 192 | { 193 | PendingNotifications.Clear(); 194 | 195 | Platform.OnForeground(); 196 | 197 | // Deserialize saved items 198 | IList loaded = Serializer?.Deserialize(Platform); 199 | 200 | if (loaded == null) 201 | { 202 | return; 203 | } 204 | 205 | foreach (IGameNotification savedNotification in loaded) 206 | { 207 | if (savedNotification.DeliveryTime > DateTime.Now) 208 | { 209 | PendingNotifications.Add(new PendingNotification(savedNotification)); 210 | } 211 | } 212 | } 213 | 214 | } 215 | -------------------------------------------------------------------------------- /ObjectPoolingX.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class ObjectPoolingX : MonoBehaviour where T: MonoBehaviour 6 | { 7 | 8 | private static ObjectPoolingX _instant; 9 | public static ObjectPoolingX Instant => _instant; 10 | 11 | private void Awake() 12 | { 13 | if (_instant == null) 14 | _instant = this; 15 | if (_instant.gameObject.GetInstanceID() != this.gameObject.GetInstanceID()) 16 | { 17 | Destroy(this.gameObject); 18 | } 19 | } 20 | 21 | 22 | Dictionary> _poolObjects = new Dictionary>(); 23 | Dictionary> _poolObjects2 = new Dictionary>(); 24 | 25 | public T GetObjectType(T key) 26 | { 27 | List _itemPool = new List(); 28 | if (!_poolObjects.ContainsKey(key)) 29 | { 30 | _poolObjects.Add(key, _itemPool); 31 | } 32 | else 33 | { 34 | _itemPool = _poolObjects[key]; 35 | } 36 | 37 | 38 | foreach (T g in _itemPool) 39 | { 40 | if (g.gameObject.activeSelf) 41 | continue; 42 | return g; 43 | } 44 | 45 | T g2 = Instantiate(key, this.transform.position, Quaternion.identity); 46 | _poolObjects[key].Add(g2); 47 | return g2; 48 | 49 | } 50 | 51 | public GameObject GetObject(GameObject key) 52 | { 53 | List _itemPool = new List(); 54 | if (!_poolObjects2.ContainsKey(key)) 55 | { 56 | _poolObjects2.Add(key, _itemPool); 57 | } 58 | else 59 | { 60 | _itemPool = _poolObjects2[key]; 61 | } 62 | 63 | 64 | foreach (GameObject g in _itemPool) 65 | { 66 | if (g.gameObject.activeSelf) 67 | continue; 68 | return g; 69 | } 70 | 71 | GameObject g2 = Instantiate(key, this.transform.position, Quaternion.identity); 72 | _poolObjects2[key].Add(g2); 73 | return g2; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /ObjectPooling_base.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class ObjectPooling_base : MonoBehaviour where T : MonoBehaviour where L: MonoBehaviour 6 | { 7 | private static T instant = null; 8 | public static T Instant{ 9 | get{ 10 | if(instant ==null){ 11 | T[] Ts = FindObjectsOfType(); 12 | if(Ts.Length > 0) 13 | instant = Ts[0]; 14 | } 15 | 16 | return instant; 17 | } 18 | } 19 | 20 | void Awake(){ 21 | Destroy(this); 22 | } 23 | 24 | [SerializeField] 25 | GameObject Obj_prefab; 26 | List List_obj = new List(); 27 | 28 | 29 | protected L Get_Obj(){ 30 | foreach(L G in List_obj){ 31 | if( G.gameObject.activeSelf){ 32 | continue; 33 | } 34 | return G; 35 | } 36 | 37 | L G2 = Instantiate(Obj_prefab,this.transform.position,Quaternion.identity,this.transform).GetComponent(); 38 | List_obj.Add(G2); 39 | G2.gameObject.SetActive(false); 40 | return G2; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Paralax.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | [Serializable] 7 | public class BackGround 8 | { 9 | public Transform _backGround; 10 | public float _damping = 0.5f; 11 | } 12 | 13 | public class Paralax : MonoBehaviour { 14 | public enum Mode 15 | { 16 | Horizontal, 17 | Vertical, 18 | HorizontalAndVertical 19 | } 20 | 21 | public Mode parallaxMode; 22 | public List _backGrounds; 23 | 24 | private float[] scales; 25 | private Transform cam; 26 | private Vector3 previousCamPos; 27 | private Vector3 position; 28 | 29 | void Awake() 30 | { 31 | cam = Camera.main.transform; 32 | } 33 | 34 | void Start() 35 | { 36 | previousCamPos = cam.position; 37 | scales = new float[_backGrounds.Count]; 38 | 39 | for (int i = 0; i < _backGrounds.Count; i++) 40 | { 41 | if (_backGrounds[i] != null) scales[i] = _backGrounds[i]._backGround.position.z * -1; 42 | } 43 | } 44 | 45 | void Update() 46 | { 47 | for (int i = 0; i < _backGrounds.Count; i++) 48 | { 49 | if (_backGrounds[i] != null) 50 | { 51 | Vector3 parallax = (previousCamPos - cam.position) * scales[i]; 52 | 53 | switch (parallaxMode) 54 | { 55 | case Mode.Horizontal: 56 | position = new Vector3(_backGrounds[i]._backGround.position.x + parallax.x, 57 | _backGrounds[i]._backGround.position.y, _backGrounds[i]._backGround.position.z); 58 | break; 59 | case Mode.Vertical: 60 | position = new Vector3(_backGrounds[i]._backGround.position.x, 61 | _backGrounds[i]._backGround.position.y + parallax.y, _backGrounds[i]._backGround.position.z); 62 | break; 63 | case Mode.HorizontalAndVertical: 64 | position = new Vector3(_backGrounds[i]._backGround.position.x + parallax.x, 65 | _backGrounds[i]._backGround.position.y + parallax.y, _backGrounds[i]._backGround.position.z); 66 | break; 67 | } 68 | 69 | _backGrounds[i]._backGround.position = Vector3.Lerp(_backGrounds[i]._backGround.position, position, _backGrounds[i]._damping * Time.deltaTime); 70 | } 71 | } 72 | previousCamPos = cam.position; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /ParticalControll.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class ParticalControll : MonoBehaviour 6 | { 7 | ParticleSystem[] sub = null; 8 | void Awake(){ 9 | sub = GetComponentsInChildren(); 10 | } 11 | // Start is called before the first frame update 12 | 13 | void OnEnable(){ 14 | StartCoroutine(CheckIfAlive()); 15 | } 16 | void Start() 17 | { 18 | 19 | } 20 | 21 | // Update is called once per frame 22 | void Update() 23 | { 24 | 25 | } 26 | 27 | IEnumerator CheckIfAlive () 28 | { 29 | ParticleSystem ps = this.GetComponent(); 30 | 31 | yield return new WaitUntil(()=>!ps.IsAlive(true)); 32 | foreach(ParticleSystem p in sub){ 33 | yield return new WaitUntil(()=>!p.IsAlive(true)); 34 | } 35 | this.gameObject.SetActive(false); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /PathCreater.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class PathCreater : MonoBehaviour 6 | { 7 | [SerializeField] 8 | int Num_Path = 2; 9 | [SerializeField] 10 | List ShowPos = new List(); 11 | [SerializeField] 12 | List Path = new List(); 13 | public int Count => Path.Count; 14 | 15 | public Vector2 GetPath(int ID = 0){ 16 | if(ID < 0 || ID >= Path.Count){ 17 | Debug.LogError("ID invalid! "+this.gameObject.name); 18 | return Vector2.zero; 19 | } 20 | return Path[ID]; 21 | } 22 | 23 | public void SetPath(int ID,Vector2 pos){ 24 | if(ID < 0 || ID >= Path.Count){ 25 | Debug.LogError("ID invalid!"); 26 | return; 27 | } 28 | 29 | Path[ID] = pos; 30 | } 31 | #if UNITY_EDITOR 32 | 33 | void OnDrawGizmosSelected(){ 34 | if(ShowPos.Count < Num_Path){ 35 | GameObject g = new GameObject(); 36 | ShowPos.Add(g); 37 | return; 38 | } 39 | 40 | Gizmos.color = Color.yellow; 41 | for(int i = 0; i(); 84 | } 85 | 86 | bool CheckSelect(){ 87 | if (UnityEditor.Selection.activeGameObject == this.gameObject) 88 | return true; 89 | 90 | if(ShowPos.Count == 0) 91 | return false; 92 | foreach(GameObject G in ShowPos){ 93 | if(UnityEditor.Selection.activeGameObject == G) 94 | return true; 95 | } 96 | 97 | return false; 98 | } 99 | #endif 100 | } 101 | -------------------------------------------------------------------------------- /PathCreator/MovingFollowPath.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | public class MovingFollowPath : MonoBehaviour 7 | { 8 | PathCreator _path; 9 | [SerializeField] bool _autoGetPathInParent = false; 10 | [SerializeField] MoveType _moveType = MoveType.MoveTowards; 11 | [SerializeField] bool _isMoveBackWard = false; 12 | [SerializeField] float _speedMoving; 13 | 14 | int _currentIndex = 0; 15 | int _moveDir = 1; 16 | List _points => _path.getPoints(); 17 | Action _callBackOnPointReach; 18 | // Start is called before the first frame update 19 | void Start() 20 | { 21 | if (!_path) 22 | { 23 | if (_autoGetPathInParent) 24 | _path = this.GetComponentInParent(); 25 | else 26 | _path = FindObjectOfType(); 27 | } 28 | 29 | if (!_path) 30 | { 31 | Debug.LogError("This component need path creator for follow!"); 32 | } 33 | } 34 | 35 | public MovingFollowPath Init(Action callBackOnPointReach = null) 36 | { 37 | _currentIndex = 0; 38 | _moveDir = 1; 39 | 40 | this._callBackOnPointReach = callBackOnPointReach; 41 | return this; 42 | } 43 | 44 | public MovingFollowPath SetMoveType(MoveType moveType) 45 | { 46 | this._moveType = moveType; 47 | return this; 48 | } 49 | 50 | public MovingFollowPath setSpeed(float speed) 51 | { 52 | this._speedMoving = speed; 53 | return this; 54 | } 55 | 56 | 57 | 58 | // Update is called once per frame 59 | void Update() 60 | { 61 | if (!_path) 62 | { 63 | Debug.LogError("This component need path creator for follow!"); 64 | return; 65 | } 66 | 67 | switch (_moveType) 68 | { 69 | case MoveType.MoveTowards: 70 | this.transform.position = Vector3.MoveTowards(this.transform.position, _points[_currentIndex], _speedMoving * Time.deltaTime); 71 | break; 72 | case MoveType.Lerp: 73 | this.transform.position = Vector3.Lerp(this.transform.position, _points[_currentIndex], _speedMoving * Time.deltaTime); 74 | break; 75 | case MoveType.SLerp: 76 | this.transform.position = Vector3.Slerp(this.transform.position, _points[_currentIndex], _speedMoving * Time.deltaTime); 77 | break; 78 | } 79 | 80 | if (Vector2.Distance(this.transform.position, _points[_currentIndex]) < 0.5f) 81 | { 82 | this._callBackOnPointReach?.Invoke(_currentIndex); 83 | _currentIndex += _moveDir; 84 | 85 | } 86 | 87 | if (!_isMoveBackWard) 88 | { 89 | if (_currentIndex >= _points.Count) 90 | { 91 | _currentIndex = 0; 92 | return; 93 | } 94 | } 95 | 96 | if (_currentIndex >= _points.Count && _moveDir == 1) 97 | { 98 | _moveDir = -1; 99 | _currentIndex = _points.Count -2; 100 | return; 101 | } 102 | 103 | if (_currentIndex <= 0 && _moveDir == -1) 104 | { 105 | _moveDir = 1; 106 | _currentIndex = 0; 107 | return; 108 | } 109 | } 110 | } 111 | 112 | public enum MoveType 113 | { 114 | MoveTowards, 115 | Lerp, 116 | SLerp 117 | } 118 | -------------------------------------------------------------------------------- /PathCreator/PathCreator.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | 6 | [AddComponentMenu("HuyTools/PathCreator")] 7 | public class PathCreator : MonoBehaviour 8 | { 9 | [SerializeField] 10 | bool isLoop = false; 11 | [SerializeField] 12 | public List List_Points; 13 | 14 | protected Vector3 _originalTransformPosition; 15 | public Vector3 originalTransformPosition => _originalTransformPosition; 16 | 17 | protected bool _originalTransformPositionStatus = false; 18 | public bool originalTransformPositionStatus => _originalTransformPositionStatus; 19 | 20 | 21 | 22 | 23 | protected virtual void Start() 24 | { 25 | Initialization(); 26 | } 27 | 28 | protected virtual void Initialization() 29 | { 30 | 31 | if (List_Points == null || List_Points.Count < 1) 32 | { 33 | return; 34 | } 35 | 36 | if (!_originalTransformPositionStatus) 37 | { 38 | _originalTransformPositionStatus = true; 39 | _originalTransformPosition = transform.position; 40 | } 41 | transform.position = _originalTransformPosition; 42 | } 43 | 44 | public List getPoints() 45 | { 46 | List tmp = new List(); 47 | for (int i =0; i< List_Points.Count; i++) 48 | { 49 | tmp.Add(this.transform.position + List_Points[i]); 50 | } 51 | 52 | return tmp; 53 | } 54 | 55 | #if UNITY_EDITOR 56 | protected virtual void OnDrawGizmos() 57 | { 58 | if (List_Points == null) 59 | { 60 | return; 61 | } 62 | 63 | if (List_Points.Count == 0) 64 | { 65 | return; 66 | } 67 | 68 | if (_originalTransformPositionStatus == false) 69 | { 70 | _originalTransformPosition = transform.position; 71 | _originalTransformPositionStatus = true; 72 | } 73 | 74 | if(!Application.isPlaying) 75 | if (transform.hasChanged) 76 | { 77 | _originalTransformPosition = transform.position; 78 | } 79 | 80 | for (int i = 0; i < List_Points.Count; i++) 81 | { 82 | 83 | Gizmos.color = Color.green; 84 | Gizmos.DrawWireSphere(_originalTransformPosition + List_Points[i], 0.2f); 85 | 86 | if ((i + 1) < List_Points.Count) 87 | { 88 | Gizmos.color = Color.white; 89 | Gizmos.DrawLine(_originalTransformPosition + List_Points[i], _originalTransformPosition + List_Points[i + 1]); 90 | } 91 | } 92 | 93 | if (isLoop) 94 | { 95 | if (List_Points.Count <= 2) 96 | { 97 | isLoop = false; 98 | return; 99 | } 100 | 101 | Gizmos.color = Color.white; 102 | Gizmos.DrawLine(_originalTransformPosition + List_Points[List_Points.Count - 1], _originalTransformPosition + List_Points[0]); 103 | } 104 | } 105 | 106 | 107 | #endif 108 | 109 | } -------------------------------------------------------------------------------- /PathCreator/PathEditor.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | 3 | using UnityEngine; 4 | using UnityEditor; 5 | using System.Collections; 6 | using System.Net; 7 | using System.Collections.Generic; 8 | 9 | [CustomEditor(typeof(PathCreator), true)] 10 | [InitializeOnLoad] 11 | public class PathEditor : Editor 12 | { 13 | public PathCreator pathTarget 14 | { 15 | get 16 | { 17 | return (PathCreator)target; 18 | } 19 | } 20 | 21 | 22 | protected virtual void OnSceneGUI() 23 | { 24 | Handles.color = Color.green; 25 | PathCreator t = (target as PathCreator); 26 | 27 | if (t.originalTransformPositionStatus == false) 28 | { 29 | return; 30 | } 31 | 32 | 33 | ShowMousePos(); 34 | 35 | GUIStyle style = new GUIStyle(); 36 | 37 | 38 | for (int i = 0; i < t.List_Points.Count; i++) 39 | { 40 | EditorGUI.BeginChangeCheck(); 41 | 42 | Vector3 oldPoint = t.originalTransformPosition + t.List_Points[i]; 43 | 44 | 45 | style.normal.textColor = Color.yellow; 46 | Handles.Label(t.originalTransformPosition + t.List_Points[i] + (Vector3.down * 0.4f) + (Vector3.right * 0.4f), "" + i, style); 47 | 48 | Vector3 newPoint = Handles.FreeMoveHandle(oldPoint, Quaternion.identity, .5f, new Vector3(.25f, .25f, .25f), Handles.CircleHandleCap); 49 | 50 | 51 | if (EditorGUI.EndChangeCheck()) 52 | { 53 | Undo.RecordObject(target, "Free Move Handle"); 54 | t.List_Points[i] = newPoint - t.originalTransformPosition; 55 | } 56 | 57 | 58 | } 59 | } 60 | 61 | void ShowMousePos() 62 | { 63 | 64 | if (!Event.current.control) 65 | return; 66 | PathCreator t = (target as PathCreator); 67 | 68 | Vector2 mousePosition = Event.current.mousePosition; 69 | Ray ray = HandleUtility.GUIPointToWorldRay(mousePosition); 70 | mousePosition = ray.origin; 71 | 72 | GUIStyle style = new GUIStyle(); 73 | 74 | float nearestPoint = 1000; 75 | int indexNearestPoint = 0; 76 | Vector2 nearestPos = Vector3.zero; 77 | 78 | for (int i = 0; i < t.List_Points.Count-1; i++) 79 | { 80 | Vector2 mouseProject = HandleUtility.ProjectPointLine(mousePosition, t.originalTransformPosition + t.List_Points[i], t.originalTransformPosition + t.List_Points[i + 1]); 81 | 82 | if (nearestPoint > Vector2.Distance(mousePosition, mouseProject)) 83 | { 84 | nearestPoint = Vector2.Distance(mousePosition, mouseProject); 85 | indexNearestPoint = i+1; 86 | nearestPos = mouseProject; 87 | } 88 | } 89 | 90 | style.normal.textColor = Color.red; 91 | 92 | HandleUtility.Repaint(); 93 | 94 | EditorGUI.BeginChangeCheck(); 95 | 96 | Handles.DrawWireCube(nearestPos, new Vector2(1.5f,1.5f) ); 97 | 98 | if (Event.current.type == EventType.MouseDown ) 99 | { 100 | Undo.RecordObject(target, "Insert another point"); 101 | t.List_Points.Insert(indexNearestPoint, mousePosition - (Vector2)t.originalTransformPosition); 102 | } 103 | 104 | EditorGUI.EndChangeCheck(); 105 | 106 | } 107 | 108 | 109 | 110 | } 111 | 112 | #endif -------------------------------------------------------------------------------- /PathCreator/README.md: -------------------------------------------------------------------------------- 1 | # ReUseScript_Unity 2 | xem hướng dẫn sử dụng ở đây nhá => 3 | :)))) 4 | -------------------------------------------------------------------------------- /Pathfinding.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using _Scripts.Tiles; 5 | using UnityEngine; 6 | 7 | namespace Tarodev_Pathfinding._Scripts { 8 | /// 9 | /// This algorithm is written for readability. Although it would be perfectly fine in 80% of games, please 10 | /// don't use this in an RTS without first applying some optimization mentioned in the video: https://youtu.be/i0x5fj4PqP4 11 | /// If you enjoyed the explanation, be sure to subscribe! 12 | /// 13 | /// Also, setting colors and text on each hex affects performance, so removing that will also improve it marginally. 14 | /// 15 | public static class Pathfinding { 16 | private static readonly Color PathColor = new Color(0.65f, 0.35f, 0.35f); 17 | private static readonly Color OpenColor = new Color(.4f, .6f, .4f); 18 | private static readonly Color ClosedColor = new Color(0.35f, 0.4f, 0.5f); 19 | 20 | public static List FindPath(NodeBase startNode, NodeBase targetNode) { 21 | var toSearch = new List() { startNode }; 22 | var processed = new List(); 23 | 24 | while (toSearch.Any()) { 25 | var current = toSearch[0]; 26 | foreach (var t in toSearch) 27 | if (t.F < current.F || t.F == current.F && t.H < current.H) current = t; 28 | 29 | processed.Add(current); 30 | toSearch.Remove(current); 31 | 32 | current.SetColor(ClosedColor); 33 | 34 | if (current == targetNode) { 35 | var currentPathTile = targetNode; 36 | var path = new List(); 37 | var count = 100; 38 | while (currentPathTile != startNode) { 39 | path.Add(currentPathTile); 40 | currentPathTile = currentPathTile.Connection; 41 | count--; 42 | if (count < 0) throw new Exception(); 43 | Debug.Log("sdfsdf"); 44 | } 45 | 46 | foreach (var tile in path) tile.SetColor(PathColor); 47 | startNode.SetColor(PathColor); 48 | Debug.Log(path.Count); 49 | return path; 50 | } 51 | 52 | foreach (var neighbor in current.Neighbors.Where(t => t.Walkable && !processed.Contains(t))) { 53 | var inSearch = toSearch.Contains(neighbor); 54 | 55 | var costToNeighbor = current.G + current.GetDistance(neighbor); 56 | 57 | if (!inSearch || costToNeighbor < neighbor.G) { 58 | neighbor.SetG(costToNeighbor); 59 | neighbor.SetConnection(current); 60 | 61 | if (!inSearch) { 62 | neighbor.SetH(neighbor.GetDistance(targetNode)); 63 | toSearch.Add(neighbor); 64 | neighbor.SetColor(OpenColor); 65 | } 66 | } 67 | } 68 | } 69 | return null; 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ReUseScript_Unity 2 | Mấy cái script mình hay dùng đi dùng lại trong unity :v 3 | Ai lấy dùng để credit mình cái nha :3 4 | Nghía qua channel youtube của mình ở đây: https://www.youtube.com/channel/UCfEdOoUcXutQmGeDYoowxIw 5 | chơi một số game của mình ở đây: https://nhathuy7996.itch.io/ 6 | -------------------------------------------------------------------------------- /RotateEffect.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class RotateEffect : MonoBehaviour 6 | { 7 | float rota = 0; 8 | public float Rota => rota; 9 | [SerializeField] 10 | float _SpeedRotZ = 50,_SpeedRotY = 50; 11 | public float SpeedRotZ { 12 | get{return _SpeedRotZ;} 13 | set{_SpeedRotZ = value;}} 14 | 15 | // Start is called before the first frame update 16 | 17 | void OnEnable(){ 18 | this.transform.eulerAngles = new Vector3(0,0,0); 19 | rota = 0; 20 | } 21 | void Start() 22 | { 23 | 24 | } 25 | 26 | // Update is called once per frame 27 | void Update() 28 | { 29 | this.rota += Time.deltaTime*_SpeedRotZ; 30 | this.rota %= 360; 31 | if(this.rota < 0) 32 | this.rota += 360; 33 | if(GameController.Instant.STATE == GameController.GameState.RUN) 34 | this.transform.eulerAngles = new Vector3(0,0,this.rota); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SerializableDictionary.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Runtime.Serialization; 5 | using UnityEngine; 6 | 7 | public abstract class SerializableDictionaryBase 8 | { 9 | public abstract class Storage {} 10 | 11 | protected class Dictionary : System.Collections.Generic.Dictionary 12 | { 13 | public Dictionary() {} 14 | public Dictionary(IDictionary dict) : base(dict) {} 15 | public Dictionary(SerializationInfo info, StreamingContext context) : base(info, context) {} 16 | } 17 | } 18 | 19 | [Serializable] 20 | public abstract class SerializableDictionaryBase : SerializableDictionaryBase, IDictionary, IDictionary, ISerializationCallbackReceiver, IDeserializationCallback, ISerializable 21 | { 22 | Dictionary m_dict; 23 | [SerializeField] 24 | TKey[] m_keys; 25 | [SerializeField] 26 | TValueStorage[] m_values; 27 | 28 | public SerializableDictionaryBase() 29 | { 30 | m_dict = new Dictionary(); 31 | } 32 | 33 | public SerializableDictionaryBase(IDictionary dict) 34 | { 35 | m_dict = new Dictionary(dict); 36 | } 37 | 38 | protected abstract void SetValue(TValueStorage[] storage, int i, TValue value); 39 | protected abstract TValue GetValue(TValueStorage[] storage, int i); 40 | 41 | public void CopyFrom(IDictionary dict) 42 | { 43 | m_dict.Clear(); 44 | foreach (var kvp in dict) 45 | { 46 | m_dict[kvp.Key] = kvp.Value; 47 | } 48 | } 49 | 50 | public void OnAfterDeserialize() 51 | { 52 | if(m_keys != null && m_values != null && m_keys.Length == m_values.Length) 53 | { 54 | m_dict.Clear(); 55 | int n = m_keys.Length; 56 | for(int i = 0; i < n; ++i) 57 | { 58 | m_dict[m_keys[i]] = GetValue(m_values, i); 59 | } 60 | 61 | m_keys = null; 62 | m_values = null; 63 | } 64 | } 65 | 66 | public void OnBeforeSerialize() 67 | { 68 | int n = m_dict.Count; 69 | m_keys = new TKey[n]; 70 | m_values = new TValueStorage[n]; 71 | 72 | int i = 0; 73 | foreach(var kvp in m_dict) 74 | { 75 | m_keys[i] = kvp.Key; 76 | SetValue(m_values, i, kvp.Value); 77 | ++i; 78 | } 79 | } 80 | 81 | #region IDictionary 82 | 83 | public ICollection Keys { get { return ((IDictionary)m_dict).Keys; } } 84 | public ICollection Values { get { return ((IDictionary)m_dict).Values; } } 85 | public int Count { get { return ((IDictionary)m_dict).Count; } } 86 | public bool IsReadOnly { get { return ((IDictionary)m_dict).IsReadOnly; } } 87 | 88 | public TValue this[TKey key] 89 | { 90 | get { return ((IDictionary)m_dict)[key]; } 91 | set { ((IDictionary)m_dict)[key] = value; } 92 | } 93 | 94 | public void Add(TKey key, TValue value) 95 | { 96 | ((IDictionary)m_dict).Add(key, value); 97 | } 98 | 99 | public bool ContainsKey(TKey key) 100 | { 101 | return ((IDictionary)m_dict).ContainsKey(key); 102 | } 103 | 104 | public bool Remove(TKey key) 105 | { 106 | return ((IDictionary)m_dict).Remove(key); 107 | } 108 | 109 | public bool TryGetValue(TKey key, out TValue value) 110 | { 111 | return ((IDictionary)m_dict).TryGetValue(key, out value); 112 | } 113 | 114 | public void Add(KeyValuePair item) 115 | { 116 | ((IDictionary)m_dict).Add(item); 117 | } 118 | 119 | public void Clear() 120 | { 121 | ((IDictionary)m_dict).Clear(); 122 | } 123 | 124 | public bool Contains(KeyValuePair item) 125 | { 126 | return ((IDictionary)m_dict).Contains(item); 127 | } 128 | 129 | public void CopyTo(KeyValuePair[] array, int arrayIndex) 130 | { 131 | ((IDictionary)m_dict).CopyTo(array, arrayIndex); 132 | } 133 | 134 | public bool Remove(KeyValuePair item) 135 | { 136 | return ((IDictionary)m_dict).Remove(item); 137 | } 138 | 139 | public IEnumerator> GetEnumerator() 140 | { 141 | return ((IDictionary)m_dict).GetEnumerator(); 142 | } 143 | 144 | IEnumerator IEnumerable.GetEnumerator() 145 | { 146 | return ((IDictionary)m_dict).GetEnumerator(); 147 | } 148 | 149 | #endregion 150 | 151 | #region IDictionary 152 | 153 | public bool IsFixedSize { get { return ((IDictionary)m_dict).IsFixedSize; } } 154 | ICollection IDictionary.Keys { get { return ((IDictionary)m_dict).Keys; } } 155 | ICollection IDictionary.Values { get { return ((IDictionary)m_dict).Values; } } 156 | public bool IsSynchronized { get { return ((IDictionary)m_dict).IsSynchronized; } } 157 | public object SyncRoot { get { return ((IDictionary)m_dict).SyncRoot; } } 158 | 159 | public object this[object key] 160 | { 161 | get { return ((IDictionary)m_dict)[key]; } 162 | set { ((IDictionary)m_dict)[key] = value; } 163 | } 164 | 165 | public void Add(object key, object value) 166 | { 167 | ((IDictionary)m_dict).Add(key, value); 168 | } 169 | 170 | public bool Contains(object key) 171 | { 172 | return ((IDictionary)m_dict).Contains(key); 173 | } 174 | 175 | IDictionaryEnumerator IDictionary.GetEnumerator() 176 | { 177 | return ((IDictionary)m_dict).GetEnumerator(); 178 | } 179 | 180 | public void Remove(object key) 181 | { 182 | ((IDictionary)m_dict).Remove(key); 183 | } 184 | 185 | public void CopyTo(Array array, int index) 186 | { 187 | ((IDictionary)m_dict).CopyTo(array, index); 188 | } 189 | 190 | #endregion 191 | 192 | #region IDeserializationCallback 193 | 194 | public void OnDeserialization(object sender) 195 | { 196 | ((IDeserializationCallback)m_dict).OnDeserialization(sender); 197 | } 198 | 199 | #endregion 200 | 201 | #region ISerializable 202 | 203 | protected SerializableDictionaryBase(SerializationInfo info, StreamingContext context) 204 | { 205 | m_dict = new Dictionary(info, context); 206 | } 207 | 208 | public void GetObjectData(SerializationInfo info, StreamingContext context) 209 | { 210 | ((ISerializable)m_dict).GetObjectData(info, context); 211 | } 212 | 213 | #endregion 214 | } 215 | 216 | public static class SerializableDictionary 217 | { 218 | public class Storage : SerializableDictionaryBase.Storage 219 | { 220 | public T data; 221 | } 222 | } 223 | 224 | public class SerializableDictionary : SerializableDictionaryBase 225 | { 226 | public SerializableDictionary() {} 227 | public SerializableDictionary(IDictionary dict) : base(dict) {} 228 | protected SerializableDictionary(SerializationInfo info, StreamingContext context) : base(info, context) {} 229 | 230 | protected override TValue GetValue(TValue[] storage, int i) 231 | { 232 | return storage[i]; 233 | } 234 | 235 | protected override void SetValue(TValue[] storage, int i, TValue value) 236 | { 237 | storage[i] = value; 238 | } 239 | } 240 | 241 | public class SerializableDictionary : SerializableDictionaryBase where TValueStorage : SerializableDictionary.Storage, new() 242 | { 243 | public SerializableDictionary() {} 244 | public SerializableDictionary(IDictionary dict) : base(dict) {} 245 | protected SerializableDictionary(SerializationInfo info, StreamingContext context) : base(info, context) {} 246 | 247 | protected override TValue GetValue(TValueStorage[] storage, int i) 248 | { 249 | return storage[i].data; 250 | } 251 | 252 | protected override void SetValue(TValueStorage[] storage, int i, TValue value) 253 | { 254 | storage[i] = new TValueStorage(); 255 | storage[i].data = value; 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /ShowDebug.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhathuy7996/ReUseScript_Unity/4aa91d90bf757c82774baf3a3bb86d4ea2a514ef/ShowDebug.unitypackage -------------------------------------------------------------------------------- /SimpleJSON.cs: -------------------------------------------------------------------------------- 1 | /* * * * * 2 | * A simple JSON Parser / builder 3 | * ------------------------------ 4 | * 5 | * It mainly has been written as a simple JSON parser. It can build a JSON string 6 | * from the node-tree, or generate a node tree from any valid JSON string. 7 | * 8 | * If you want to use compression when saving to file / stream / B64 you have to include 9 | * SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) in your project and 10 | * define "USE_SharpZipLib" at the top of the file 11 | * 12 | * Written by Bunny83 13 | * 2012-06-09 14 | * 15 | * [2012-06-09 First Version] 16 | * - provides strongly typed node classes and lists / dictionaries 17 | * - provides easy access to class members / array items / data values 18 | * - the parser now properly identifies types. So generating JSON with this framework should work. 19 | * - only double quotes (") are used for quoting strings. 20 | * - provides "casting" properties to easily convert to / from those types: 21 | * int / float / double / bool 22 | * - provides a common interface for each node so no explicit casting is required. 23 | * - the parser tries to avoid errors, but if malformed JSON is parsed the result is more or less undefined 24 | * - It can serialize/deserialize a node tree into/from an experimental compact binary format. It might 25 | * be handy if you want to store things in a file and don't want it to be easily modifiable 26 | * 27 | * [2012-12-17 Update] 28 | * - Added internal JSONLazyCreator class which simplifies the construction of a JSON tree 29 | * Now you can simple reference any item that doesn't exist yet and it will return a JSONLazyCreator 30 | * The class determines the required type by it's further use, creates the type and removes itself. 31 | * - Added binary serialization / deserialization. 32 | * - Added support for BZip2 zipped binary format. Requires the SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) 33 | * The usage of the SharpZipLib library can be disabled by removing or commenting out the USE_SharpZipLib define at the top 34 | * - The serializer uses different types when it comes to store the values. Since my data values 35 | * are all of type string, the serializer will "try" which format fits best. The order is: int, float, double, bool, string. 36 | * It's not the most efficient way but for a moderate amount of data it should work on all platforms. 37 | * 38 | * [2017-03-08 Update] 39 | * - Optimised parsing by using a StringBuilder for token. This prevents performance issues when large 40 | * string data fields are contained in the json data. 41 | * - Finally refactored the badly named JSONClass into JSONObject. 42 | * - Replaced the old JSONData class by distict typed classes ( JSONString, JSONNumber, JSONBool, JSONNull ) this 43 | * allows to propertly convert the node tree back to json without type information loss. The actual value 44 | * parsing now happens at parsing time and not when you actually access one of the casting properties. 45 | * 46 | * [2017-04-11 Update] 47 | * - Fixed parsing bug where empty string values have been ignored. 48 | * - Optimised "ToString" by using a StringBuilder internally. This should heavily improve performance for large files 49 | * - Changed the overload of "ToString(string aIndent)" to "ToString(int aIndent)" 50 | * 51 | * [2017-11-29 Update] 52 | * - Removed the IEnumerator implementations on JSONArray & JSONObject and replaced it with a common 53 | * struct Enumerator in JSONNode that should avoid garbage generation. The enumerator always works 54 | * on KeyValuePair, even for JSONArray. 55 | * - Added two wrapper Enumerators that allows for easy key or value enumeration. A JSONNode now has 56 | * a "Keys" and a "Values" enumerable property. Those are also struct enumerators / enumerables 57 | * - A KeyValuePair can now be implicitly converted into a JSONNode. This allows 58 | * a foreach loop over a JSONNode to directly access the values only. Since KeyValuePair as well as 59 | * all the Enumerators are structs, no garbage is allocated. 60 | * - To add Linq support another "LinqEnumerator" is available through the "Linq" property. This 61 | * enumerator does implement the generic IEnumerable interface so most Linq extensions can be used 62 | * on this enumerable object. This one does allocate memory as it's a wrapper class. 63 | * - The Escape method now escapes all control characters (# < 32) in strings as uncode characters 64 | * (\uXXXX) and if the static bool JSONNode.forceASCII is set to true it will also escape all 65 | * characters # > 127. This might be useful if you require an ASCII output. Though keep in mind 66 | * when your strings contain many non-ascii characters the strings become much longer (x6) and are 67 | * no longer human readable. 68 | * - The node types JSONObject and JSONArray now have an "Inline" boolean switch which will default to 69 | * false. It can be used to serialize this element inline even you serialize with an indented format 70 | * This is useful for arrays containing numbers so it doesn't place every number on a new line 71 | * - Extracted the binary serialization code into a seperate extension file. All classes are now declared 72 | * as "partial" so an extension file can even add a new virtual or abstract method / interface to 73 | * JSONNode and override it in the concrete type classes. It's of course a hacky approach which is 74 | * generally not recommended, but i wanted to keep everything tightly packed. 75 | * - Added a static CreateOrGet method to the JSONNull class. Since this class is immutable it could 76 | * be reused without major problems. If you have a lot null fields in your data it will help reduce 77 | * the memory / garbage overhead. I also added a static setting (reuseSameInstance) to JSONNull 78 | * (default is true) which will change the behaviour of "CreateOrGet". If you set this to false 79 | * CreateOrGet will not reuse the cached instance but instead create a new JSONNull instance each time. 80 | * I made the JSONNull constructor private so if you need to create an instance manually use 81 | * JSONNull.CreateOrGet() 82 | * 83 | * [2018-01-09 Update] 84 | * - Changed all double.TryParse and double.ToString uses to use the invariant culture to avoid problems 85 | * on systems with a culture that uses a comma as decimal point. 86 | * 87 | * [2018-01-26 Update] 88 | * - Added AsLong. Note that a JSONNumber is stored as double and can't represent all long values. However 89 | * storing it as string would work. 90 | * - Added static setting "JSONNode.longAsString" which controls the default type that is used by the 91 | * LazyCreator when using AsLong 92 | * 93 | * 94 | * The MIT License (MIT) 95 | * 96 | * Copyright (c) 2012-2017 Markus Göbel (Bunny83) 97 | * 98 | * Permission is hereby granted, free of charge, to any person obtaining a copy 99 | * of this software and associated documentation files (the "Software"), to deal 100 | * in the Software without restriction, including without limitation the rights 101 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 102 | * copies of the Software, and to permit persons to whom the Software is 103 | * furnished to do so, subject to the following conditions: 104 | * 105 | * The above copyright notice and this permission notice shall be included in all 106 | * copies or substantial portions of the Software. 107 | * 108 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 109 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 110 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 111 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 112 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 113 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 114 | * SOFTWARE. 115 | * 116 | * * * * */ 117 | using System; 118 | using System.Collections; 119 | using System.Collections.Generic; 120 | using System.Globalization; 121 | using System.Linq; 122 | using System.Text; 123 | 124 | namespace SimpleJSON 125 | { 126 | public enum JSONNodeType 127 | { 128 | Array = 1, 129 | Object = 2, 130 | String = 3, 131 | Number = 4, 132 | NullValue = 5, 133 | Boolean = 6, 134 | None = 7, 135 | Custom = 0xFF, 136 | } 137 | public enum JSONTextMode 138 | { 139 | Compact, 140 | Indent 141 | } 142 | 143 | public abstract partial class JSONNode 144 | { 145 | #region Enumerators 146 | public struct Enumerator 147 | { 148 | private enum Type { None, Array, Object } 149 | private Type type; 150 | private Dictionary.Enumerator m_Object; 151 | private List.Enumerator m_Array; 152 | public bool IsValid { get { return type != Type.None; } } 153 | public Enumerator(List.Enumerator aArrayEnum) 154 | { 155 | type = Type.Array; 156 | m_Object = default(Dictionary.Enumerator); 157 | m_Array = aArrayEnum; 158 | } 159 | public Enumerator(Dictionary.Enumerator aDictEnum) 160 | { 161 | type = Type.Object; 162 | m_Object = aDictEnum; 163 | m_Array = default(List.Enumerator); 164 | } 165 | public KeyValuePair Current 166 | { 167 | get { 168 | if (type == Type.Array) 169 | return new KeyValuePair(string.Empty, m_Array.Current); 170 | else if (type == Type.Object) 171 | return m_Object.Current; 172 | return new KeyValuePair(string.Empty, null); 173 | } 174 | } 175 | public bool MoveNext() 176 | { 177 | if (type == Type.Array) 178 | return m_Array.MoveNext(); 179 | else if (type == Type.Object) 180 | return m_Object.MoveNext(); 181 | return false; 182 | } 183 | } 184 | public struct ValueEnumerator 185 | { 186 | private Enumerator m_Enumerator; 187 | public ValueEnumerator(List.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } 188 | public ValueEnumerator(Dictionary.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } 189 | public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } 190 | public JSONNode Current { get { return m_Enumerator.Current.Value; } } 191 | public bool MoveNext() { return m_Enumerator.MoveNext(); } 192 | public ValueEnumerator GetEnumerator() { return this; } 193 | } 194 | public struct KeyEnumerator 195 | { 196 | private Enumerator m_Enumerator; 197 | public KeyEnumerator(List.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } 198 | public KeyEnumerator(Dictionary.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } 199 | public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } 200 | public JSONNode Current { get { return m_Enumerator.Current.Key; } } 201 | public bool MoveNext() { return m_Enumerator.MoveNext(); } 202 | public KeyEnumerator GetEnumerator() { return this; } 203 | } 204 | 205 | public class LinqEnumerator : IEnumerator>, IEnumerable> 206 | { 207 | private JSONNode m_Node; 208 | private Enumerator m_Enumerator; 209 | internal LinqEnumerator(JSONNode aNode) 210 | { 211 | m_Node = aNode; 212 | if (m_Node != null) 213 | m_Enumerator = m_Node.GetEnumerator(); 214 | } 215 | public KeyValuePair Current { get { return m_Enumerator.Current; } } 216 | object IEnumerator.Current { get { return m_Enumerator.Current; } } 217 | public bool MoveNext() { return m_Enumerator.MoveNext(); } 218 | 219 | public void Dispose() 220 | { 221 | m_Node = null; 222 | m_Enumerator = new Enumerator(); 223 | } 224 | 225 | public IEnumerator> GetEnumerator() 226 | { 227 | return new LinqEnumerator(m_Node); 228 | } 229 | 230 | public void Reset() 231 | { 232 | if (m_Node != null) 233 | m_Enumerator = m_Node.GetEnumerator(); 234 | } 235 | 236 | IEnumerator IEnumerable.GetEnumerator() 237 | { 238 | return new LinqEnumerator(m_Node); 239 | } 240 | } 241 | 242 | #endregion Enumerators 243 | 244 | #region common interface 245 | 246 | public static bool forceASCII = false; // Use Unicode by default 247 | public static bool longAsString = false; // lazy creator creates a JSONString instead of JSONNumber 248 | 249 | public abstract JSONNodeType Tag { get; } 250 | 251 | public virtual JSONNode this[int aIndex] { get { return null; } set { } } 252 | 253 | public virtual JSONNode this[string aKey] { get { return null; } set { } } 254 | 255 | public virtual string Value { get { return ""; } set { } } 256 | 257 | public virtual int Count { get { return 0; } } 258 | 259 | public virtual bool IsNumber { get { return false; } } 260 | public virtual bool IsString { get { return false; } } 261 | public virtual bool IsBoolean { get { return false; } } 262 | public virtual bool IsNull { get { return false; } } 263 | public virtual bool IsArray { get { return false; } } 264 | public virtual bool IsObject { get { return false; } } 265 | 266 | public virtual bool Inline { get { return false; } set { } } 267 | 268 | public virtual void Add(string aKey, JSONNode aItem) 269 | { 270 | } 271 | public virtual void Add(JSONNode aItem) 272 | { 273 | Add("", aItem); 274 | } 275 | 276 | public virtual JSONNode Remove(string aKey) 277 | { 278 | return null; 279 | } 280 | 281 | public virtual JSONNode Remove(int aIndex) 282 | { 283 | return null; 284 | } 285 | 286 | public virtual JSONNode Remove(JSONNode aNode) 287 | { 288 | return aNode; 289 | } 290 | 291 | public virtual IEnumerable Children 292 | { 293 | get 294 | { 295 | yield break; 296 | } 297 | } 298 | 299 | public IEnumerable DeepChildren 300 | { 301 | get 302 | { 303 | foreach (var C in Children) 304 | foreach (var D in C.DeepChildren) 305 | yield return D; 306 | } 307 | } 308 | 309 | public override string ToString() 310 | { 311 | StringBuilder sb = new StringBuilder(); 312 | WriteToStringBuilder(sb, 0, 0, JSONTextMode.Compact); 313 | return sb.ToString(); 314 | } 315 | 316 | public virtual string ToString(int aIndent) 317 | { 318 | StringBuilder sb = new StringBuilder(); 319 | WriteToStringBuilder(sb, 0, aIndent, JSONTextMode.Indent); 320 | return sb.ToString(); 321 | } 322 | internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode); 323 | 324 | public abstract Enumerator GetEnumerator(); 325 | public IEnumerable> Linq { get { return new LinqEnumerator(this); } } 326 | public KeyEnumerator Keys { get { return new KeyEnumerator(GetEnumerator()); } } 327 | public ValueEnumerator Values { get { return new ValueEnumerator(GetEnumerator()); } } 328 | 329 | #endregion common interface 330 | 331 | #region typecasting properties 332 | 333 | 334 | public virtual double AsDouble 335 | { 336 | get 337 | { 338 | double v = 0.0; 339 | if (double.TryParse(Value,NumberStyles.Float, CultureInfo.InvariantCulture, out v)) 340 | return v; 341 | return 0.0; 342 | } 343 | set 344 | { 345 | Value = value.ToString(CultureInfo.InvariantCulture); 346 | } 347 | } 348 | 349 | public virtual int AsInt 350 | { 351 | get { return (int)AsDouble; } 352 | set { AsDouble = value; } 353 | } 354 | 355 | public virtual float AsFloat 356 | { 357 | get { return (float)AsDouble; } 358 | set { AsDouble = value; } 359 | } 360 | 361 | public virtual bool AsBool 362 | { 363 | get 364 | { 365 | bool v = false; 366 | if (bool.TryParse(Value, out v)) 367 | return v; 368 | return !string.IsNullOrEmpty(Value); 369 | } 370 | set 371 | { 372 | Value = (value) ? "true" : "false"; 373 | } 374 | } 375 | 376 | public virtual long AsLong 377 | { 378 | get 379 | { 380 | long val = 0; 381 | if (long.TryParse(Value, out val)) 382 | return val; 383 | return 0L; 384 | } 385 | set 386 | { 387 | Value = value.ToString(); 388 | } 389 | } 390 | 391 | public virtual JSONArray AsArray 392 | { 393 | get 394 | { 395 | return this as JSONArray; 396 | } 397 | } 398 | 399 | public virtual JSONObject AsObject 400 | { 401 | get 402 | { 403 | return this as JSONObject; 404 | } 405 | } 406 | 407 | 408 | #endregion typecasting properties 409 | 410 | #region operators 411 | 412 | public static implicit operator JSONNode(string s) 413 | { 414 | return new JSONString(s); 415 | } 416 | public static implicit operator string(JSONNode d) 417 | { 418 | return (d == null) ? null : d.Value; 419 | } 420 | 421 | public static implicit operator JSONNode(double n) 422 | { 423 | return new JSONNumber(n); 424 | } 425 | public static implicit operator double(JSONNode d) 426 | { 427 | return (d == null) ? 0 : d.AsDouble; 428 | } 429 | 430 | public static implicit operator JSONNode(float n) 431 | { 432 | return new JSONNumber(n); 433 | } 434 | public static implicit operator float(JSONNode d) 435 | { 436 | return (d == null) ? 0 : d.AsFloat; 437 | } 438 | 439 | public static implicit operator JSONNode(int n) 440 | { 441 | return new JSONNumber(n); 442 | } 443 | public static implicit operator int(JSONNode d) 444 | { 445 | return (d == null) ? 0 : d.AsInt; 446 | } 447 | 448 | public static implicit operator JSONNode(long n) 449 | { 450 | if (longAsString) 451 | return new JSONString(n.ToString()); 452 | return new JSONNumber(n); 453 | } 454 | public static implicit operator long(JSONNode d) 455 | { 456 | return (d == null) ? 0L : d.AsLong; 457 | } 458 | 459 | public static implicit operator JSONNode(bool b) 460 | { 461 | return new JSONBool(b); 462 | } 463 | public static implicit operator bool(JSONNode d) 464 | { 465 | return (d == null) ? false : d.AsBool; 466 | } 467 | 468 | public static implicit operator JSONNode(KeyValuePair aKeyValue) 469 | { 470 | return aKeyValue.Value; 471 | } 472 | 473 | public static bool operator ==(JSONNode a, object b) 474 | { 475 | if (ReferenceEquals(a, b)) 476 | return true; 477 | bool aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator; 478 | bool bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator; 479 | if (aIsNull && bIsNull) 480 | return true; 481 | return !aIsNull && a.Equals(b); 482 | } 483 | 484 | public static bool operator !=(JSONNode a, object b) 485 | { 486 | return !(a == b); 487 | } 488 | 489 | public override bool Equals(object obj) 490 | { 491 | return ReferenceEquals(this, obj); 492 | } 493 | 494 | public override int GetHashCode() 495 | { 496 | return base.GetHashCode(); 497 | } 498 | 499 | #endregion operators 500 | 501 | [ThreadStatic] 502 | private static StringBuilder m_EscapeBuilder; 503 | internal static StringBuilder EscapeBuilder 504 | { 505 | get { 506 | if (m_EscapeBuilder == null) 507 | m_EscapeBuilder = new StringBuilder(); 508 | return m_EscapeBuilder; 509 | } 510 | } 511 | internal static string Escape(string aText) 512 | { 513 | var sb = EscapeBuilder; 514 | sb.Length = 0; 515 | if (sb.Capacity < aText.Length + aText.Length / 10) 516 | sb.Capacity = aText.Length + aText.Length / 10; 517 | foreach (char c in aText) 518 | { 519 | switch (c) 520 | { 521 | case '\\': 522 | sb.Append("\\\\"); 523 | break; 524 | case '\"': 525 | sb.Append("\\\""); 526 | break; 527 | case '\n': 528 | sb.Append("\\n"); 529 | break; 530 | case '\r': 531 | sb.Append("\\r"); 532 | break; 533 | case '\t': 534 | sb.Append("\\t"); 535 | break; 536 | case '\b': 537 | sb.Append("\\b"); 538 | break; 539 | case '\f': 540 | sb.Append("\\f"); 541 | break; 542 | default: 543 | if (c < ' ' || (forceASCII && c > 127)) 544 | { 545 | ushort val = c; 546 | sb.Append("\\u").Append(val.ToString("X4")); 547 | } 548 | else 549 | sb.Append(c); 550 | break; 551 | } 552 | } 553 | string result = sb.ToString(); 554 | sb.Length = 0; 555 | return result; 556 | } 557 | 558 | static void ParseElement(JSONNode ctx, string token, string tokenName, bool quoted) 559 | { 560 | if (quoted) 561 | { 562 | ctx.Add(tokenName, token); 563 | return; 564 | } 565 | string tmp = token.ToLower(); 566 | if (tmp == "false" || tmp == "true") 567 | ctx.Add(tokenName, tmp == "true"); 568 | else if (tmp == "null") 569 | ctx.Add(tokenName, null); 570 | else 571 | { 572 | double val; 573 | if (double.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out val)) 574 | ctx.Add(tokenName, val); 575 | else 576 | ctx.Add(tokenName, token); 577 | } 578 | } 579 | 580 | public static JSONNode Parse(string aJSON) 581 | { 582 | Stack stack = new Stack(); 583 | JSONNode ctx = null; 584 | int i = 0; 585 | StringBuilder Token = new StringBuilder(); 586 | string TokenName = ""; 587 | bool QuoteMode = false; 588 | bool TokenIsQuoted = false; 589 | while (i < aJSON.Length) 590 | { 591 | switch (aJSON[i]) 592 | { 593 | case '{': 594 | if (QuoteMode) 595 | { 596 | Token.Append(aJSON[i]); 597 | break; 598 | } 599 | stack.Push(new JSONObject()); 600 | if (ctx != null) 601 | { 602 | ctx.Add(TokenName, stack.Peek()); 603 | } 604 | TokenName = ""; 605 | Token.Length = 0; 606 | ctx = stack.Peek(); 607 | break; 608 | 609 | case '[': 610 | if (QuoteMode) 611 | { 612 | Token.Append(aJSON[i]); 613 | break; 614 | } 615 | 616 | stack.Push(new JSONArray()); 617 | if (ctx != null) 618 | { 619 | ctx.Add(TokenName, stack.Peek()); 620 | } 621 | TokenName = ""; 622 | Token.Length = 0; 623 | ctx = stack.Peek(); 624 | break; 625 | 626 | case '}': 627 | case ']': 628 | if (QuoteMode) 629 | { 630 | 631 | Token.Append(aJSON[i]); 632 | break; 633 | } 634 | if (stack.Count == 0) 635 | throw new Exception("JSON Parse: Too many closing brackets"); 636 | 637 | stack.Pop(); 638 | if (Token.Length > 0 || TokenIsQuoted) 639 | { 640 | ParseElement(ctx, Token.ToString(), TokenName, TokenIsQuoted); 641 | TokenIsQuoted = false; 642 | } 643 | TokenName = ""; 644 | Token.Length = 0; 645 | if (stack.Count > 0) 646 | ctx = stack.Peek(); 647 | break; 648 | 649 | case ':': 650 | if (QuoteMode) 651 | { 652 | Token.Append(aJSON[i]); 653 | break; 654 | } 655 | TokenName = Token.ToString(); 656 | Token.Length = 0; 657 | TokenIsQuoted = false; 658 | break; 659 | 660 | case '"': 661 | QuoteMode ^= true; 662 | TokenIsQuoted |= QuoteMode; 663 | break; 664 | 665 | case ',': 666 | if (QuoteMode) 667 | { 668 | Token.Append(aJSON[i]); 669 | break; 670 | } 671 | if (Token.Length > 0 || TokenIsQuoted) 672 | { 673 | ParseElement(ctx, Token.ToString(), TokenName, TokenIsQuoted); 674 | TokenIsQuoted = false; 675 | } 676 | TokenName = ""; 677 | Token.Length = 0; 678 | TokenIsQuoted = false; 679 | break; 680 | 681 | case '\r': 682 | case '\n': 683 | break; 684 | 685 | case ' ': 686 | case '\t': 687 | if (QuoteMode) 688 | Token.Append(aJSON[i]); 689 | break; 690 | 691 | case '\\': 692 | ++i; 693 | if (QuoteMode) 694 | { 695 | char C = aJSON[i]; 696 | switch (C) 697 | { 698 | case 't': 699 | Token.Append('\t'); 700 | break; 701 | case 'r': 702 | Token.Append('\r'); 703 | break; 704 | case 'n': 705 | Token.Append('\n'); 706 | break; 707 | case 'b': 708 | Token.Append('\b'); 709 | break; 710 | case 'f': 711 | Token.Append('\f'); 712 | break; 713 | case 'u': 714 | { 715 | string s = aJSON.Substring(i + 1, 4); 716 | Token.Append((char)int.Parse( 717 | s, 718 | System.Globalization.NumberStyles.AllowHexSpecifier)); 719 | i += 4; 720 | break; 721 | } 722 | default: 723 | Token.Append(C); 724 | break; 725 | } 726 | } 727 | break; 728 | 729 | default: 730 | Token.Append(aJSON[i]); 731 | break; 732 | } 733 | ++i; 734 | } 735 | if (QuoteMode) 736 | { 737 | throw new Exception("JSON Parse: Quotation marks seems to be messed up."); 738 | } 739 | return ctx; 740 | } 741 | 742 | } 743 | // End of JSONNode 744 | 745 | public partial class JSONArray : JSONNode 746 | { 747 | private List m_List = new List(); 748 | 749 | 750 | private bool inline = false; 751 | public override bool Inline 752 | { 753 | get { return inline; } 754 | set { inline = value; } 755 | } 756 | 757 | public override JSONNodeType Tag { get { return JSONNodeType.Array; } } 758 | public override bool IsArray { get { return true; } } 759 | public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); } 760 | 761 | public override JSONNode this[int aIndex] 762 | { 763 | get 764 | { 765 | if (aIndex < 0 || aIndex >= m_List.Count) 766 | return new JSONLazyCreator(this); 767 | return m_List[aIndex]; 768 | } 769 | set 770 | { 771 | if (value == null) 772 | value = JSONNull.CreateOrGet(); 773 | if (aIndex < 0 || aIndex >= m_List.Count) 774 | m_List.Add(value); 775 | else 776 | m_List[aIndex] = value; 777 | } 778 | } 779 | 780 | public override JSONNode this[string aKey] 781 | { 782 | get { return new JSONLazyCreator(this); } 783 | set 784 | { 785 | if (value == null) 786 | value = JSONNull.CreateOrGet(); 787 | m_List.Add(value); 788 | } 789 | } 790 | 791 | public override int Count 792 | { 793 | get { return m_List.Count; } 794 | } 795 | 796 | public override void Add(string aKey, JSONNode aItem) 797 | { 798 | if (aItem == null) 799 | aItem = JSONNull.CreateOrGet(); 800 | m_List.Add(aItem); 801 | } 802 | 803 | public override JSONNode Remove(int aIndex) 804 | { 805 | if (aIndex < 0 || aIndex >= m_List.Count) 806 | return null; 807 | JSONNode tmp = m_List[aIndex]; 808 | m_List.RemoveAt(aIndex); 809 | return tmp; 810 | } 811 | 812 | public override JSONNode Remove(JSONNode aNode) 813 | { 814 | m_List.Remove(aNode); 815 | return aNode; 816 | } 817 | 818 | public override IEnumerable Children 819 | { 820 | get 821 | { 822 | foreach (JSONNode N in m_List) 823 | yield return N; 824 | } 825 | } 826 | 827 | 828 | internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) 829 | { 830 | aSB.Append('['); 831 | int count = m_List.Count; 832 | if (inline) 833 | aMode = JSONTextMode.Compact; 834 | for (int i = 0; i < count; i++) 835 | { 836 | if (i > 0) 837 | aSB.Append(','); 838 | if (aMode == JSONTextMode.Indent) 839 | aSB.AppendLine(); 840 | 841 | if (aMode == JSONTextMode.Indent) 842 | aSB.Append(' ', aIndent + aIndentInc); 843 | m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); 844 | } 845 | if (aMode == JSONTextMode.Indent) 846 | aSB.AppendLine().Append(' ', aIndent); 847 | aSB.Append(']'); 848 | } 849 | } 850 | // End of JSONArray 851 | 852 | public partial class JSONObject : JSONNode 853 | { 854 | private Dictionary m_Dict = new Dictionary(); 855 | 856 | private bool inline = false; 857 | public override bool Inline 858 | { 859 | get { return inline; } 860 | set { inline = value; } 861 | } 862 | 863 | public override JSONNodeType Tag { get { return JSONNodeType.Object; } } 864 | public override bool IsObject { get { return true; } } 865 | 866 | public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); } 867 | 868 | 869 | public override JSONNode this[string aKey] 870 | { 871 | get 872 | { 873 | if (m_Dict.ContainsKey(aKey)) 874 | return m_Dict[aKey]; 875 | else 876 | return new JSONLazyCreator(this, aKey); 877 | } 878 | set 879 | { 880 | if (value == null) 881 | value = JSONNull.CreateOrGet(); 882 | if (m_Dict.ContainsKey(aKey)) 883 | m_Dict[aKey] = value; 884 | else 885 | m_Dict.Add(aKey, value); 886 | } 887 | } 888 | 889 | public override JSONNode this[int aIndex] 890 | { 891 | get 892 | { 893 | if (aIndex < 0 || aIndex >= m_Dict.Count) 894 | return null; 895 | return m_Dict.ElementAt(aIndex).Value; 896 | } 897 | set 898 | { 899 | if (value == null) 900 | value = JSONNull.CreateOrGet(); 901 | if (aIndex < 0 || aIndex >= m_Dict.Count) 902 | return; 903 | string key = m_Dict.ElementAt(aIndex).Key; 904 | m_Dict[key] = value; 905 | } 906 | } 907 | 908 | public override int Count 909 | { 910 | get { return m_Dict.Count; } 911 | } 912 | 913 | public override void Add(string aKey, JSONNode aItem) 914 | { 915 | if (aItem == null) 916 | aItem = JSONNull.CreateOrGet(); 917 | 918 | if (!string.IsNullOrEmpty(aKey)) 919 | { 920 | if (m_Dict.ContainsKey(aKey)) 921 | m_Dict[aKey] = aItem; 922 | else 923 | m_Dict.Add(aKey, aItem); 924 | } 925 | else 926 | m_Dict.Add(Guid.NewGuid().ToString(), aItem); 927 | } 928 | 929 | public override JSONNode Remove(string aKey) 930 | { 931 | if (!m_Dict.ContainsKey(aKey)) 932 | return null; 933 | JSONNode tmp = m_Dict[aKey]; 934 | m_Dict.Remove(aKey); 935 | return tmp; 936 | } 937 | 938 | public override JSONNode Remove(int aIndex) 939 | { 940 | if (aIndex < 0 || aIndex >= m_Dict.Count) 941 | return null; 942 | var item = m_Dict.ElementAt(aIndex); 943 | m_Dict.Remove(item.Key); 944 | return item.Value; 945 | } 946 | 947 | public override JSONNode Remove(JSONNode aNode) 948 | { 949 | try 950 | { 951 | var item = m_Dict.Where(k => k.Value == aNode).First(); 952 | m_Dict.Remove(item.Key); 953 | return aNode; 954 | } 955 | catch 956 | { 957 | return null; 958 | } 959 | } 960 | 961 | public override IEnumerable Children 962 | { 963 | get 964 | { 965 | foreach (KeyValuePair N in m_Dict) 966 | yield return N.Value; 967 | } 968 | } 969 | 970 | internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) 971 | { 972 | aSB.Append('{'); 973 | bool first = true; 974 | if (inline) 975 | aMode = JSONTextMode.Compact; 976 | foreach (var k in m_Dict) 977 | { 978 | if (!first) 979 | aSB.Append(','); 980 | first = false; 981 | if (aMode == JSONTextMode.Indent) 982 | aSB.AppendLine(); 983 | if (aMode == JSONTextMode.Indent) 984 | aSB.Append(' ', aIndent + aIndentInc); 985 | aSB.Append('\"').Append(Escape(k.Key)).Append('\"'); 986 | if (aMode == JSONTextMode.Compact) 987 | aSB.Append(':'); 988 | else 989 | aSB.Append(" : "); 990 | k.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); 991 | } 992 | if (aMode == JSONTextMode.Indent) 993 | aSB.AppendLine().Append(' ', aIndent); 994 | aSB.Append('}'); 995 | } 996 | 997 | } 998 | // End of JSONObject 999 | 1000 | public partial class JSONString : JSONNode 1001 | { 1002 | private string m_Data; 1003 | 1004 | public override JSONNodeType Tag { get { return JSONNodeType.String; } } 1005 | public override bool IsString { get { return true; } } 1006 | 1007 | public override Enumerator GetEnumerator() { return new Enumerator(); } 1008 | 1009 | 1010 | public override string Value 1011 | { 1012 | get { return m_Data; } 1013 | set 1014 | { 1015 | m_Data = value; 1016 | } 1017 | } 1018 | 1019 | public JSONString(string aData) 1020 | { 1021 | m_Data = aData; 1022 | } 1023 | 1024 | internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) 1025 | { 1026 | aSB.Append('\"').Append(Escape(m_Data)).Append('\"'); 1027 | } 1028 | public override bool Equals(object obj) 1029 | { 1030 | if (base.Equals(obj)) 1031 | return true; 1032 | string s = obj as string; 1033 | if (s != null) 1034 | return m_Data == s; 1035 | JSONString s2 = obj as JSONString; 1036 | if (s2 != null) 1037 | return m_Data == s2.m_Data; 1038 | return false; 1039 | } 1040 | public override int GetHashCode() 1041 | { 1042 | return m_Data.GetHashCode(); 1043 | } 1044 | } 1045 | // End of JSONString 1046 | 1047 | public partial class JSONNumber : JSONNode 1048 | { 1049 | private double m_Data; 1050 | 1051 | public override JSONNodeType Tag { get { return JSONNodeType.Number; } } 1052 | public override bool IsNumber { get { return true; } } 1053 | public override Enumerator GetEnumerator() { return new Enumerator(); } 1054 | 1055 | public override string Value 1056 | { 1057 | get { return m_Data.ToString(CultureInfo.InvariantCulture); } 1058 | set 1059 | { 1060 | double v; 1061 | if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out v)) 1062 | m_Data = v; 1063 | } 1064 | } 1065 | 1066 | public override double AsDouble 1067 | { 1068 | get { return m_Data; } 1069 | set { m_Data = value; } 1070 | } 1071 | public override long AsLong 1072 | { 1073 | get { return (long)m_Data; } 1074 | set { m_Data = value; } 1075 | } 1076 | 1077 | public JSONNumber(double aData) 1078 | { 1079 | m_Data = aData; 1080 | } 1081 | 1082 | public JSONNumber(string aData) 1083 | { 1084 | Value = aData; 1085 | } 1086 | 1087 | internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) 1088 | { 1089 | aSB.Append(Value); 1090 | } 1091 | private static bool IsNumeric(object value) 1092 | { 1093 | return value is int || value is uint 1094 | || value is float || value is double 1095 | || value is decimal 1096 | || value is long || value is ulong 1097 | || value is short || value is ushort 1098 | || value is sbyte || value is byte; 1099 | } 1100 | public override bool Equals(object obj) 1101 | { 1102 | if (obj == null) 1103 | return false; 1104 | if (base.Equals(obj)) 1105 | return true; 1106 | JSONNumber s2 = obj as JSONNumber; 1107 | if (s2 != null) 1108 | return m_Data == s2.m_Data; 1109 | if (IsNumeric(obj)) 1110 | return Convert.ToDouble(obj) == m_Data; 1111 | return false; 1112 | } 1113 | public override int GetHashCode() 1114 | { 1115 | return m_Data.GetHashCode(); 1116 | } 1117 | } 1118 | // End of JSONNumber 1119 | 1120 | public partial class JSONBool : JSONNode 1121 | { 1122 | private bool m_Data; 1123 | 1124 | public override JSONNodeType Tag { get { return JSONNodeType.Boolean; } } 1125 | public override bool IsBoolean { get { return true; } } 1126 | public override Enumerator GetEnumerator() { return new Enumerator(); } 1127 | 1128 | public override string Value 1129 | { 1130 | get { return m_Data.ToString(); } 1131 | set 1132 | { 1133 | bool v; 1134 | if (bool.TryParse(value, out v)) 1135 | m_Data = v; 1136 | } 1137 | } 1138 | public override bool AsBool 1139 | { 1140 | get { return m_Data; } 1141 | set { m_Data = value; } 1142 | } 1143 | 1144 | public JSONBool(bool aData) 1145 | { 1146 | m_Data = aData; 1147 | } 1148 | 1149 | public JSONBool(string aData) 1150 | { 1151 | Value = aData; 1152 | } 1153 | 1154 | internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) 1155 | { 1156 | aSB.Append((m_Data) ? "true" : "false"); 1157 | } 1158 | public override bool Equals(object obj) 1159 | { 1160 | if (obj == null) 1161 | return false; 1162 | if (obj is bool) 1163 | return m_Data == (bool)obj; 1164 | return false; 1165 | } 1166 | public override int GetHashCode() 1167 | { 1168 | return m_Data.GetHashCode(); 1169 | } 1170 | } 1171 | // End of JSONBool 1172 | 1173 | public partial class JSONNull : JSONNode 1174 | { 1175 | static JSONNull m_StaticInstance = new JSONNull(); 1176 | public static bool reuseSameInstance = true; 1177 | public static JSONNull CreateOrGet() 1178 | { 1179 | if (reuseSameInstance) 1180 | return m_StaticInstance; 1181 | return new JSONNull(); 1182 | } 1183 | private JSONNull() { } 1184 | 1185 | public override JSONNodeType Tag { get { return JSONNodeType.NullValue; } } 1186 | public override bool IsNull { get { return true; } } 1187 | public override Enumerator GetEnumerator() { return new Enumerator(); } 1188 | 1189 | public override string Value 1190 | { 1191 | get { return "null"; } 1192 | set { } 1193 | } 1194 | public override bool AsBool 1195 | { 1196 | get { return false; } 1197 | set { } 1198 | } 1199 | 1200 | public override bool Equals(object obj) 1201 | { 1202 | if (object.ReferenceEquals(this, obj)) 1203 | return true; 1204 | return (obj is JSONNull); 1205 | } 1206 | public override int GetHashCode() 1207 | { 1208 | return 0; 1209 | } 1210 | 1211 | internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) 1212 | { 1213 | aSB.Append("null"); 1214 | } 1215 | } 1216 | // End of JSONNull 1217 | 1218 | internal partial class JSONLazyCreator : JSONNode 1219 | { 1220 | private JSONNode m_Node = null; 1221 | private string m_Key = null; 1222 | public override JSONNodeType Tag { get { return JSONNodeType.None; } } 1223 | public override Enumerator GetEnumerator() { return new Enumerator(); } 1224 | 1225 | public JSONLazyCreator(JSONNode aNode) 1226 | { 1227 | m_Node = aNode; 1228 | m_Key = null; 1229 | } 1230 | 1231 | public JSONLazyCreator(JSONNode aNode, string aKey) 1232 | { 1233 | m_Node = aNode; 1234 | m_Key = aKey; 1235 | } 1236 | 1237 | private void Set(JSONNode aVal) 1238 | { 1239 | if (m_Key == null) 1240 | { 1241 | m_Node.Add(aVal); 1242 | } 1243 | else 1244 | { 1245 | m_Node.Add(m_Key, aVal); 1246 | } 1247 | m_Node = null; // Be GC friendly. 1248 | } 1249 | 1250 | public override JSONNode this[int aIndex] 1251 | { 1252 | get 1253 | { 1254 | return new JSONLazyCreator(this); 1255 | } 1256 | set 1257 | { 1258 | var tmp = new JSONArray(); 1259 | tmp.Add(value); 1260 | Set(tmp); 1261 | } 1262 | } 1263 | 1264 | public override JSONNode this[string aKey] 1265 | { 1266 | get 1267 | { 1268 | return new JSONLazyCreator(this, aKey); 1269 | } 1270 | set 1271 | { 1272 | var tmp = new JSONObject(); 1273 | tmp.Add(aKey, value); 1274 | Set(tmp); 1275 | } 1276 | } 1277 | 1278 | public override void Add(JSONNode aItem) 1279 | { 1280 | var tmp = new JSONArray(); 1281 | tmp.Add(aItem); 1282 | Set(tmp); 1283 | } 1284 | 1285 | public override void Add(string aKey, JSONNode aItem) 1286 | { 1287 | var tmp = new JSONObject(); 1288 | tmp.Add(aKey, aItem); 1289 | Set(tmp); 1290 | } 1291 | 1292 | public static bool operator ==(JSONLazyCreator a, object b) 1293 | { 1294 | if (b == null) 1295 | return true; 1296 | return System.Object.ReferenceEquals(a, b); 1297 | } 1298 | 1299 | public static bool operator !=(JSONLazyCreator a, object b) 1300 | { 1301 | return !(a == b); 1302 | } 1303 | 1304 | public override bool Equals(object obj) 1305 | { 1306 | if (obj == null) 1307 | return true; 1308 | return System.Object.ReferenceEquals(this, obj); 1309 | } 1310 | 1311 | public override int GetHashCode() 1312 | { 1313 | return 0; 1314 | } 1315 | 1316 | public override int AsInt 1317 | { 1318 | get 1319 | { 1320 | JSONNumber tmp = new JSONNumber(0); 1321 | Set(tmp); 1322 | return 0; 1323 | } 1324 | set 1325 | { 1326 | JSONNumber tmp = new JSONNumber(value); 1327 | Set(tmp); 1328 | } 1329 | } 1330 | 1331 | public override float AsFloat 1332 | { 1333 | get 1334 | { 1335 | JSONNumber tmp = new JSONNumber(0.0f); 1336 | Set(tmp); 1337 | return 0.0f; 1338 | } 1339 | set 1340 | { 1341 | JSONNumber tmp = new JSONNumber(value); 1342 | Set(tmp); 1343 | } 1344 | } 1345 | 1346 | public override double AsDouble 1347 | { 1348 | get 1349 | { 1350 | JSONNumber tmp = new JSONNumber(0.0); 1351 | Set(tmp); 1352 | return 0.0; 1353 | } 1354 | set 1355 | { 1356 | JSONNumber tmp = new JSONNumber(value); 1357 | Set(tmp); 1358 | } 1359 | } 1360 | 1361 | public override long AsLong 1362 | { 1363 | get 1364 | { 1365 | if (longAsString) 1366 | Set(new JSONString("0")); 1367 | else 1368 | Set(new JSONNumber(0.0)); 1369 | return 0L; 1370 | } 1371 | set 1372 | { 1373 | if (longAsString) 1374 | Set(new JSONString(value.ToString())); 1375 | else 1376 | Set(new JSONNumber(value)); 1377 | } 1378 | } 1379 | 1380 | public override bool AsBool 1381 | { 1382 | get 1383 | { 1384 | JSONBool tmp = new JSONBool(false); 1385 | Set(tmp); 1386 | return false; 1387 | } 1388 | set 1389 | { 1390 | JSONBool tmp = new JSONBool(value); 1391 | Set(tmp); 1392 | } 1393 | } 1394 | 1395 | public override JSONArray AsArray 1396 | { 1397 | get 1398 | { 1399 | JSONArray tmp = new JSONArray(); 1400 | Set(tmp); 1401 | return tmp; 1402 | } 1403 | } 1404 | 1405 | public override JSONObject AsObject 1406 | { 1407 | get 1408 | { 1409 | JSONObject tmp = new JSONObject(); 1410 | Set(tmp); 1411 | return tmp; 1412 | } 1413 | } 1414 | internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) 1415 | { 1416 | aSB.Append("null"); 1417 | } 1418 | } 1419 | // End of JSONLazyCreator 1420 | 1421 | public static class JSON 1422 | { 1423 | public static JSONNode Parse(string aJSON) 1424 | { 1425 | return JSONNode.Parse(aJSON); 1426 | } 1427 | } 1428 | } 1429 | -------------------------------------------------------------------------------- /Singleton.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace HuynnLib 6 | { 7 | public class Singleton : MonoBehaviour where T : MonoBehaviour 8 | { 9 | 10 | private static T _instant = null; 11 | public static T Instant 12 | { 13 | get 14 | { 15 | if (_instant == null) 16 | { 17 | if (FindObjectOfType() != null) 18 | _instant = FindObjectOfType(); 19 | else 20 | new GameObject().AddComponent().name = "Singleton_"+ typeof(T).ToString(); 21 | } 22 | 23 | return _instant; 24 | } 25 | } 26 | 27 | void Awake() 28 | { 29 | if (_instant != null && _instant.gameObject.GetInstanceID() != this.gameObject.GetInstanceID()) 30 | { 31 | Debug.LogError("Singleton already exist "+ _instant.gameObject.name); 32 | Destroy(this.gameObject); 33 | } 34 | else 35 | _instant = this.GetComponent(); 36 | } 37 | // Start is called before the first frame update 38 | void Start() 39 | { 40 | 41 | } 42 | 43 | // Update is called once per frame 44 | void Update() 45 | { 46 | 47 | } 48 | 49 | 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /Sound.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhathuy7996/ReUseScript_Unity/4aa91d90bf757c82774baf3a3bb86d4ea2a514ef/Sound.zip -------------------------------------------------------------------------------- /Sound/DestroySound.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class DestroySound : MonoBehaviour 6 | { 7 | [SerializeField] 8 | AudioSource _Audio = null; 9 | public AudioSource Audio => _Audio; 10 | // Start is called before the first frame update 11 | void Awake() 12 | { 13 | _Audio = this.GetComponent(); 14 | 15 | } 16 | 17 | void Start(){ 18 | StartCoroutine(WaitDone()); 19 | } 20 | 21 | // Update is called once per frame 22 | void Update() 23 | { 24 | 25 | } 26 | 27 | IEnumerator WaitDone(){ 28 | yield return new WaitUntil(()=>!_Audio.isPlaying); 29 | this.gameObject.SetActive(false); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sound/SoundManager.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | 6 | [RequireComponent(typeof(AudioListener))] 7 | public class SoundManager : Singleton 8 | { 9 | [SerializeField] 10 | DestroySound Audio_Prefab = null; 11 | [SerializeField] 12 | List AudioS = new List(); 13 | [SerializeField] 14 | List SoundFiles = new List(); 15 | 16 | void Start(){ 17 | Object[] file = Resources.LoadAll("Sound", typeof(AudioClip)); 18 | foreach(Object o in file){ 19 | SoundFiles.Add((AudioClip)o); 20 | } 21 | } 22 | 23 | public void PlaySound(string nameSound){ 24 | foreach(AudioClip A in SoundFiles){ 25 | if(A.name.ToLower() != nameSound.ToLower()) 26 | continue; 27 | AudioSource source = GetAudioSource(); 28 | 29 | source.clip = A; 30 | source.gameObject.SetActive(true); 31 | } 32 | } 33 | AudioSource GetAudioSource(){ 34 | foreach(DestroySound D in AudioS){ 35 | if(D.gameObject.activeSelf) 36 | continue; 37 | return D.Audio; 38 | } 39 | 40 | DestroySound D2 = Instantiate(Audio_Prefab,this.transform.position,Quaternion.identity,this.transform).GetComponent(); 41 | AudioS.Add(D2); 42 | D2.gameObject.SetActive(false); 43 | 44 | return D2.Audio; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ThrowObject.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public class ThrowObject : MonoBehaviour 6 | { 7 | [SerializeField] 8 | Transform StartPoint = null,EndPoint = null; 9 | [SerializeField] 10 | int Angle = 0,Trajectory_num = 100; 11 | [SerializeField] 12 | float V = 0,Config = 0.1f; 13 | float Angle_Rad = 0; 14 | [SerializeField] 15 | GameObject Bullet = null; 16 | 17 | // Start is called before the first frame update 18 | void Start() 19 | { 20 | 21 | } 22 | 23 | // Update is called once per frame 24 | void Update() 25 | { 26 | 27 | } 28 | 29 | public void Fire(){ 30 | CalV(); 31 | GameObject B = Instantiate(Bullet,StartPoint.transform.position,Quaternion.identity); 32 | Vector3 Force = Vector3.zero; 33 | Force.x = V * 50 * Mathf.Cos(Angle_Rad); 34 | Force.y = V * 50 * Mathf.Sin(Angle_Rad); 35 | B.GetComponent().AddForce(Force); 36 | } 37 | 38 | void CalV(){ 39 | 40 | float Y = EndPoint.transform.position.y - StartPoint.transform.position.y; 41 | float X = EndPoint.transform.position.x - StartPoint.transform.position.x; 42 | 43 | if(X < 0){ 44 | Angle_Rad = -Mathf.Abs(Angle) * Mathf.Deg2Rad; 45 | Config = -Mathf.Abs(Config); 46 | }else{ 47 | Angle_Rad = Mathf.Abs(Angle) * Mathf.Deg2Rad; 48 | Config = Mathf.Abs(Config); 49 | } 50 | 51 | 52 | float v2 = ( 10 / ( (Mathf.Tan(Angle_Rad) * X - Y)/ (X*X) ) ) / (2 * Mathf.Cos(Angle_Rad) * Mathf.Cos(Angle_Rad)); 53 | v2 = Mathf.Abs(v2); 54 | V = Mathf.Sqrt(v2); 55 | } 56 | 57 | void OnDrawGizmosSelected(){ 58 | 59 | CalV(); 60 | 61 | Gizmos.color = Color.red; 62 | 63 | for(int i = 0; i< Trajectory_num; i++){ 64 | float time = i * Config; 65 | float X = V * Mathf.Cos(Angle_Rad) * time; 66 | float Y = V * Mathf.Sin(Angle_Rad) * time - 0.5f * (10 * time * time); 67 | 68 | Vector3 pos1 = StartPoint.transform.position + new Vector3(X,Y,0); 69 | 70 | time = (i+1) * Config; 71 | X = V * Mathf.Cos(Angle_Rad) * time; 72 | Y = V * Mathf.Sin(Angle_Rad) * time - 0.5f * (10 * time * time); 73 | 74 | Vector3 pos2 = StartPoint.transform.position + new Vector3(X,Y,0); 75 | 76 | Gizmos.DrawLine(pos1,pos2); 77 | } 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /Transperant Shader/HuynnShader.shader: -------------------------------------------------------------------------------- 1 | // Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 | 3 | Shader "HuynnShader" 4 | { 5 | Properties 6 | { 7 | _Color("Color", Color) = (1,1,1,1) 8 | _MainTex("Albedo", 2D) = "white" {} 9 | 10 | 11 | 12 | // Blending state 13 | [HideInInspector] _Mode ("__mode", Float) = 0.0 14 | [HideInInspector] _SrcBlend ("__src", Float) = 1.0 15 | [HideInInspector] _DstBlend ("__dst", Float) = 0.0 16 | [HideInInspector] _ZWrite ("__zw", Float) = 1.0 17 | } 18 | 19 | CGINCLUDE 20 | #define UNITY_SETUP_BRDF_INPUT MetallicSetup 21 | ENDCG 22 | 23 | 24 | 25 | SubShader 26 | { 27 | Tags { "RenderType"="Opaque" "PerformanceChecks"="False" } 28 | LOD 150 29 | 30 | // ------------------------------------------------------------------ 31 | // Base forward pass (directional light, emission, lightmaps, ...) 32 | Pass 33 | { 34 | Name "FORWARD" 35 | Tags { "LightMode" = "ForwardBase" } 36 | 37 | Blend [_SrcBlend] [_DstBlend] 38 | ZWrite [_ZWrite] 39 | 40 | CGPROGRAM 41 | #pragma target 2.0 42 | 43 | #pragma shader_feature_local _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON 44 | 45 | 46 | #pragma multi_compile_fwdbase 47 | 48 | #pragma vertex vertBase 49 | #pragma fragment fragBase 50 | #include "UnityStandardCoreForward.cginc" 51 | 52 | ENDCG 53 | } 54 | 55 | 56 | } 57 | 58 | 59 | FallBack "VertexLit" 60 | CustomEditor "HuynnStandardShaderGUI" 61 | } -------------------------------------------------------------------------------- /Transperant Shader/MaterialExtensions.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | public static class MaterialExtensions 3 | { 4 | public static void ToOpaqueMode(this Material material) 5 | { 6 | material.SetOverrideTag("RenderType", ""); 7 | material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); 8 | material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); 9 | material.SetInt("_ZWrite", 1); 10 | material.DisableKeyword("_ALPHATEST_ON"); 11 | material.DisableKeyword("_ALPHABLEND_ON"); 12 | material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); 13 | material.renderQueue = -1; 14 | } 15 | 16 | public static void ToFadeMode(this Material material) 17 | { 18 | material.SetOverrideTag("RenderType", "Transparent"); 19 | material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); 20 | material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); 21 | material.SetInt("_ZWrite", 0); 22 | material.DisableKeyword("_ALPHATEST_ON"); 23 | material.EnableKeyword("_ALPHABLEND_ON"); 24 | material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); 25 | material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; 26 | } 27 | } -------------------------------------------------------------------------------- /UnityMainThread.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using System; 5 | 6 | internal class UnityMainThread : MonoBehaviour 7 | { 8 | internal static UnityMainThread wkr; 9 | Queue jobs = new Queue(); 10 | 11 | void Awake() 12 | { 13 | wkr = this; 14 | } 15 | 16 | void Update() 17 | { 18 | while (jobs.Count > 0) 19 | jobs.Dequeue().Invoke(); 20 | } 21 | 22 | internal void AddJob(Action newJob) 23 | { 24 | jobs.Enqueue(newJob); 25 | } 26 | } -------------------------------------------------------------------------------- /VisionCone.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using Unity.VisualScripting; 4 | using UnityEngine; 5 | 6 | public class VisionCone : MonoBehaviour 7 | { 8 | public Material VisionConeMaterial; 9 | public float VisionRange; 10 | public float VisionAngle; 11 | public LayerMask VisionObstructingLayer;//layer with objects that obstruct the enemy view, like walls, for example 12 | public int VisionConeResolution = 120;//the vision cone will be made up of triangles, the higher this value is the pretier the vision cone will be 13 | Mesh VisionConeMesh; 14 | MeshFilter MeshFilter_; 15 | //Create all of these variables, most of them are self explanatory, but for the ones that aren't i've added a comment to clue you in on what they do 16 | //for the ones that you dont understand dont worry, just follow along 17 | void Start() 18 | { 19 | transform.AddComponent().material = VisionConeMaterial; 20 | MeshFilter_ = transform.AddComponent(); 21 | VisionConeMesh = new Mesh(); 22 | VisionAngle *= Mathf.Deg2Rad; 23 | } 24 | 25 | 26 | void Update() 27 | { 28 | DrawVisionCone();//calling the vision cone function everyframe just so the cone is updated every frame 29 | } 30 | 31 | void DrawVisionCone()//this method creates the vision cone mesh 32 | { 33 | int[] triangles = new int[(VisionConeResolution - 1) * 3]; 34 | Vector3[] Vertices = new Vector3[VisionConeResolution + 1]; 35 | Vertices[0] = Vector3.zero; 36 | float Currentangle = -VisionAngle / 2; 37 | float angleIcrement = VisionAngle / (VisionConeResolution - 1); 38 | float Sine; 39 | float Cosine; 40 | 41 | for (int i = 0; i < VisionConeResolution; i++) 42 | { 43 | Sine = Mathf.Sin(Currentangle); 44 | Cosine = Mathf.Cos(Currentangle); 45 | Vector3 RaycastDirection = (transform.forward * Cosine) + (transform.right * Sine); 46 | Vector3 VertForward = (Vector3.forward * Cosine) + (Vector3.right * Sine); 47 | if (Physics.Raycast(transform.position, RaycastDirection, out RaycastHit hit, VisionRange, VisionObstructingLayer)) 48 | { 49 | Vertices[i + 1] = VertForward * hit.distance; 50 | } 51 | else 52 | { 53 | Vertices[i + 1] = VertForward * VisionRange; 54 | } 55 | 56 | 57 | Currentangle += angleIcrement; 58 | } 59 | for (int i = 0, j = 0; i < triangles.Length; i += 3, j++) 60 | { 61 | triangles[i] = 0; 62 | triangles[i + 1] = j + 1; 63 | triangles[i + 2] = j + 2; 64 | } 65 | VisionConeMesh.Clear(); 66 | VisionConeMesh.vertices = Vertices; 67 | VisionConeMesh.triangles = triangles; 68 | MeshFilter_.mesh = VisionConeMesh; 69 | } 70 | 71 | 72 | } -------------------------------------------------------------------------------- /skybox.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nhathuy7996/ReUseScript_Unity/4aa91d90bf757c82774baf3a3bb86d4ea2a514ef/skybox.unitypackage --------------------------------------------------------------------------------