RandomGFGoStop/Assets/Scripts/My/DSUtil.cs

991 lines
32 KiB
C#

using UnityEngine;
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Security.Cryptography;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Text.RegularExpressions;
using System.Reflection;
using Random = UnityEngine.Random;
using UnityEngine.AI;
#if UNITY_EDITOR
using UnityEditor;
#endif
public delegate void VoidDelegate();
public static partial class DSUtil
{
// --------------------------------------------------------------------
// 로그 관련 함수
// String객체
private static StringBuilder m_strBuilder = new StringBuilder(1024);
public static StringBuilder DSString
{
get
{
m_strBuilder.Remove(0, m_strBuilder.Length);
return m_strBuilder;
}
}
// String조립
public static string Format(string strMessage, params object[] args)
{
StringBuilder strBuilder = DSString;
strBuilder.AppendFormat(strMessage, args);
return strBuilder.ToString();
}
// 로그 : 에러
public static void LogError(string strMessage, params object[] args)
{
Verify(false, Format(strMessage, args));
}
// 로그 : 워닝
public static void LogWarning(string strMessage, params object[] args)
{
#if UNITY_EDITOR
UnityEngine.Debug.LogWarning(Format(strMessage, args));
#endif
}
// 로그 : 일반
public static void Log(string strMessage, params object[] args)
{
#if UNITY_EDITOR
UnityEngine.Debug.Log(Format(strMessage, args));
#endif
}
// 서버로그 : 에러값
public static void LogErrorToServer(int iErrorCode, string strMessage = "")
{
string strErrorMessage = string.Empty;
switch (iErrorCode)
{
// MAP_CONST[5] = "Http 프로토콜 에러";
// TimeOut 도 포함.
case 5:
//strErrorMessage = "Timed Out.. Please Retry..";
strErrorMessage = "시간이 초과되었습니다. 다시 시도해주세요.";
break;
default:
break;
}
// 메시지가 있으면 덮어 씀.
if (false == string.IsNullOrEmpty(strMessage))
{
strErrorMessage = strMessage;
}
DSUtil.LogError(strErrorMessage);
}
// 예외 : try-Catch문에서 예외전달메시지
public static System.ArgumentException GetExceptionMsg(string strMessage, params object[] args)
{
return new System.ArgumentException(Format(strMessage, args));
}
// 예외 : 에러로그와 리턴값을 하나로 묶음( EX : return ErrorReturn<bool>(false, "{0} 예외야!!", "나쁜"); )
public static T ErrorReturn<T>(T tReturnValue, string strMessage, params object[] args)
{
LogError(strMessage, args);
return tReturnValue;
}
// 정보 : 콜스택을 얻습니다.
public static StackFrame[] GetCallStack()
{
StackTrace stackTrace = new StackTrace();
return stackTrace.GetFrames();
}
// --------------------------------------------------------------------
// 형 변환 관련
// 형변환 : String을 Enum으로
// Enum.Parse 엄청느립니다. 가급적 사용금지!!!
public static T FormatStringToEnum<T>(string _strTypeName, params object[] args)
{
return StringToEnum<T>(Format(_strTypeName, args));
}
public static T StringToEnum<T>(string _strTypeName)
{
_strTypeName = _strTypeName.Replace(" ", "");
if (true == string.IsNullOrEmpty(_strTypeName) || false == Enum.IsDefined(typeof(T), _strTypeName))
{
LogWarning("[Not Defined " + typeof(T) + " ] " + _strTypeName);
return default(T);
}
return (T)Enum.Parse(typeof(T), _strTypeName);
}
public static T CheerSoundStringToEnum<T>(string _strTypeName)
{
_strTypeName = _strTypeName.Replace(" ", "");
if (true == string.IsNullOrEmpty(_strTypeName) || false == Enum.IsDefined(typeof(T), _strTypeName))
return default(T);
return (T)Enum.Parse(typeof(T), _strTypeName);
}
// 형변환 : String을 Enum으로
// Enum.Parse 엄청느립니다. 가급적 사용금지!!!
public static T StringToEnum<T>(string strEnum, string strErrorLog)
{
strEnum = strEnum.Replace(" ", "");
if (true == string.IsNullOrEmpty(strEnum) || false == Enum.IsDefined(typeof(T), strEnum))
{
LogError("{0}(Enum:{1})", strErrorLog, strEnum);
}
// 없는 Enum이면 크래시되도록 놔두자!!
return (T)Enum.Parse(typeof(T), strEnum);
}
// 형변환 : Object을 String으로
public static string ObjectToString(System.Object _cObject)
{
if (_cObject == null)
return null;
var binaryFormatter = new BinaryFormatter();
var memoryStream = new MemoryStream();
binaryFormatter.Serialize(memoryStream, _cObject);
return Convert.ToBase64String(memoryStream.GetBuffer());
}
// 형변환 : String을 Object로
public static System.Object StringToObject(string _strValue)
{
if (true == string.IsNullOrEmpty(_strValue))
return null;
var binaryFormatter = new BinaryFormatter();
var memoryStream = new MemoryStream(Convert.FromBase64String(_strValue));
System.Object obj = binaryFormatter.Deserialize(memoryStream);
return obj;
}
// --------------------------------------------------------------------
// 컨테이너 관련
// Foreach : Enum
public static void ForeachToEnum<T>(Action<T> pLambda)
{
foreach (T eEnum in Enum.GetValues(typeof(T)))
pLambda(eEnum);
}
// Foreach : List
public static void ForeachToList<T>(List<T> list, Action<T> pLambda)
{
if (null == list)
return;
foreach (T tList in list)
pLambda(tList);
}
// Foreach : List
public static void ForeachToListOfBreak<T>(List<T> list, bool bBreakCondition, Func<T, bool> pLambda)
{
if (null == list)
return;
foreach (T tList in list)
{
if (bBreakCondition == pLambda(tList))
break;
}
}
// Foreach Dictionary
public static void ForeachToDic<TKey, TValue>(Dictionary<TKey, TValue> dic, Action<TKey, TValue> pLambda)
{
if (null == dic)
return;
foreach (KeyValuePair<TKey, TValue> kvp in dic)
pLambda(kvp.Key, kvp.Value);
}
//-------------------------------------------------------------------------
// FirstKey
// if (.NET 3.5) return dic.Keys.First();
public static Key FirstKey<Key, Value>(Dictionary<Key, Value> dic, Key defaultVal)
{
foreach (var pair in dic)
return pair.Key;
return defaultVal;
}
// dictionary 램덤키 뽑는다.
public static Key RandomKey<Key, Value>(Dictionary<Key, Value> dic, Key defaultVal)
{
if (null == dic)
return defaultVal;
if (0 == dic.Count)
return defaultVal;
System.Random rand = new System.Random();
var listKey = dic.ToList()[rand.Next(0, dic.Count)];
return listKey.Key;
}
//-------------------------------------------------------------------------
// test_code
public static void TestRandomTrue()
{
List<bool> list = new List<bool>();
var p = 0.3f;
for (int i = 0; i < 1000; i++)
list.Add(DSUtil.RandomTrue(p));
var countTrue = list.Count(e => e == true);
var countTotal = list.Count();
var ratio = (float)countTrue / (float)countTotal;
Log(" RandomTrue(" + p + "); " +
"result ratio [" + ratio + "], " +
"true count [" + countTrue + "], " +
"total count [" + countTotal + "]");
}
//-------------------------------------------------------------------------
// RandomTrue
// 확률 P% 이하로 true 리턴. (단, 100% == 1.0f)
public static bool RandomTrue(float p)
{
// 유니티 랜덤함수 직접 사용[blueasa / 2014-10-30]
return p > UnityEngine.Random.Range(0f, 1f);
}
public static bool RandomFalse(float p)
{
// 유니티 랜덤함수 직접 사용[blueasa / 2014-10-30]
return RandomTrue(1.0f - p);
}
public static bool RandomTrue(double p)
{
// 유니티 랜덤함수 직접 사용[blueasa / 2014-10-30]
return p > UnityEngine.Random.Range(0f, 1f);
}
//-------------------------------------------------------------------------
// RandomW<T>
// 가중치에 따라 랜덤하게 원소 선택
public static T RandomW<T>(List<T> values, List<float> weights)
{
if ((null == values) || (0 == values.Count))
return default(T);
if ((null == weights) || (0 == weights.Count))
return RandomN(values);
// ex: weights = { 0.1, 0.3, 0.6};
// assert(weight.Sum > 0);
var subsums = new List<float>(weights.Count);
var sum = weights.Aggregate(0.0f, (acc, f) =>
{ acc += f; subsums.Add(acc); return acc; });
// ex : subsums = {0.1, 0.4, 1.0}, sum = 1.0
var r = UnityEngine.Random.Range(0.0f, sum);
// ex : r = 0.35
var index = subsums.FindIndex(f => (r < f));
// ex : index = 1
// 2017. 08. 29. 정인호. 크래쉬 리포트(ArgumentOutOfRangeException: Argument is out of range.)에 의해 로그 추가
if (values.Count <= index || index < 0)
{
string valuesvalue = "";
for (int iLoop = 0; iLoop < values.Count; ++iLoop)
valuesvalue += values[iLoop] + ", ";
string weightsvalue = "";
for (int iLoop = 0; iLoop < weights.Count; ++iLoop)
weightsvalue += weights[iLoop] + ", ";
Assert(false, Format("DSUtil RandomW Error : values : {0}, weights : {1}, index : {2}, ", valuesvalue, weightsvalue, index));
}
return values[index];
}
//-------------------------------------------------------------------------
// RandomOneW<T>
// 가중치에 따라 랜덤하게 원소 선택 ( 무조건 하나는 선택되도록 )
// 가중치를 정규화해서 합이 1인 값으로 만들고, 의미없는 원소는 제거하여 RandomW처리
public static T RandomOneW<T>(List<T> values, List<float> weights)
{
if ((null == values) || (0 == values.Count))
return default(T);
if ((null == weights) || (0 == weights.Count))
return RandomN(values);
// 전체 가중치 합
float fSum = 0.0f;
foreach (float fValue in weights)
fSum += fValue;
// 예외처리 : 가중치 합이 0이면 선택할 원소가 없다...
if (0.0f == fSum)
return default(T);
// 데이터 복사용 변수
List<T> CopyValues = new List<T>();
List<float> CopyWeights = new List<float>();
// 가중치 정규화하면서 필요없는 원소는 제거
for (int iLoop = 0; iLoop < weights.Count; ++iLoop)
{
if (0.0f == weights[iLoop])
continue;
CopyValues.Add(values[iLoop]);
CopyWeights.Add(weights[iLoop] / fSum);
}
return RandomW(CopyValues, CopyWeights);
}
//-------------------------------------------------------------------------
// RandomN<T>
// RandomW<T> 와 스팩은 동일하나, 모든 원소의 가중치가 동일한 경우로 제한함.
public static T RandomN<T>(List<T> values)
{
if ((null == values) || (0 == values.Count))
return default(T);
var index = (int)UnityEngine.Random.Range(0.0f, values.Count);
if (index == values.Count)
index = values.Count - 1;
return values[index];
}
//-------------------------------------------------------------------------
// RandomRange
// int일 경우, Max값도 나오도록 하기 위해 Max + 1을 함.
public static int RandomRange(int _iMin, int _iMax)
{
if (_iMin == _iMax) return _iMin;
return UnityEngine.Random.Range(_iMin, _iMax + 1);
}
public static float RandomRange(float _fMin, float _fMax)
{
if (_fMin == _fMax) return _fMin;
return UnityEngine.Random.Range(_fMin, _fMax);
}
public static Vector3 RandomVector(float fMin, float fMax)
{
return RandomVector(fMin, fMax, fMin, fMax, fMin, fMax);
}
public static Vector3 RandomVector(float fMinX, float fMaxX, float fMinY, float fMaxY, float fMinZ, float fMaxZ)
{
return new Vector3(RandomRange(fMinX, fMaxX), RandomRange(fMinY, fMaxY), RandomRange(fMinZ, fMaxZ));
}
public static Vector3 RandomVector_Exception_y(float minX, float maxX, float y, float minZ, float maxZ)
{
return new Vector3(RandomRange(minX, maxX), y, RandomRange(minZ, maxZ));
}
//-------------------------------------------------------------------------
//
public static List<int> RandomIndex(int _iCount)
{
List<int> listResult = new List<int>();
List<int> listCount = new List<int>();
for (int i = 0; i < _iCount; i++)
listCount.Add(i);
while (0 < listCount.Count)
{
int iRand = UnityEngine.Random.Range(0, listCount.Count);
listResult.Add(listCount[iRand]);
listCount.RemoveAt(iRand);
}
return listResult;
}
//========================================================================
// 폴링 함수 getter 를 이용해 이벤트 드리븐 함수 onChange 를 호출
// prev - 이전값
// getter - 폴링함수.
// onChange := Action<PrevValue, CurrentValue> - 이벤트 함수.
public static void PollingToEvent(float prev, Func<float> getter, Action<float, float> onChange)
{
// 값이 변했는지 검사. 다를 때만 호출
var current = getter();
if (prev != current)
onChange(prev, current);
}
/// <summary>
/// GUID
/// </summary>
/// <returns></returns>
public static string GetGUID()
{
System.Guid uid = System.Guid.NewGuid();
return uid.ToString();
}
/// <summary>
/// UUID(이걸 사용)
/// </summary>
/// <returns></returns>
public static string GetUUID()
{
return SystemInfo.deviceUniqueIdentifier;
}
// 프리팹에 Component가 Missing된 것이 있는지 체크
public static void CheckMissingComponent()
{
UnityEngine.Object[] pObjects = Resources.FindObjectsOfTypeAll(typeof(GameObject));
foreach (UnityEngine.Object pObject in pObjects)
{
GameObject pGameObject = pObject as GameObject;
if (null == pGameObject)
continue;
Component[] pComponents = pGameObject.GetComponents<Component>();
foreach (Component pComponent in pComponents)
{
if (null == pComponent)
DSUtil.LogError("MissingComponent!!(GameObject{0})", pObject.name);
}
}
}
// 유니티 에디터의 Pause를 Toggle합니다.
public static void EditorPauseOfToggle(bool bToggle)
{
#if UNITY_EDITOR
EditorApplication.isPaused = bToggle;
#endif
}
public static void ContainsDictionary<TKey, TValue>(Dictionary<TKey, TValue> dicContainer, TKey tKey)
{
if (false == dicContainer.ContainsKey(tKey))
dicContainer[tKey] = default(TValue);
}
// 클래스 Null체크
/*
* null for classes
* null (empty) for Nullable<T>
* zero/false/etc for other structs
*/
public static bool IsNull<T>(T value)
{
if (EqualityComparer<T>.Default.Equals(value, default(T)))
return true;
return false;
}
/*
*Assert 관련
*/
public static void Assert(bool condition)
{
// if (Debug.isDebugBuild && !condition) throw new Exception();
if (!condition) throw new Exception();
}
public static void Assert(bool condition, string log)
{
// if (Debug.isDebugBuild && !condition) {
// Debug.Log (log);
// throw new Exception ();
// }
if (!condition)
{
UnityEngine.Debug.LogError(log);
throw new Exception();
}
}
public static void Assert(bool condition, string strMessage, params object[] args)
{
// if (Debug.isDebugBuild && !condition) {
// Debug.Log (Format (strMessage, args));
// throw new Exception ();
// }
if (!condition)
{
UnityEngine.Debug.Log(Format(strMessage, args));
throw new Exception();
}
}
public static void Verify(bool condition)
{
if (!condition)
{
//EditorPauseOfToggle (true);
}
}
public static void Verify(bool condition, string log)
{
if (!condition)
{
UnityEngine.Debug.LogError(log);
//EditorPauseOfToggle (true);
}
}
public static void Verify(bool condition, string strMessage, params object[] args)
{
if (!condition)
{
UnityEngine.Debug.LogError(Format(strMessage, args));
//EditorPauseOfToggle (true);
}
}
public static void Search(string strPath, Action<FileInfo> pCallBack)
{
DirectoryInfo pDirInfo = new DirectoryInfo(strPath);
SearchFiles(pDirInfo, pCallBack);
SearchDirs(pDirInfo, pCallBack);
}
static void SearchDirs(DirectoryInfo pDirInfo, Action<FileInfo> pCallBack)
{
DirectoryInfo[] pDirs = pDirInfo.GetDirectories();
foreach (DirectoryInfo pDir in pDirs)
{
SearchFiles(pDir, pCallBack);
SearchDirs(pDir, pCallBack);
}
}
static void SearchFiles(DirectoryInfo pDirInfo, Action<FileInfo> pCallBack)
{
FileInfo[] pFiles = pDirInfo.GetFiles();
foreach (FileInfo pFile in pFiles)
{
pCallBack(pFile);
}
}
public static string Encrypt(string toEncrypt, string key = "12345678901234567890123456789012") /*key limit 32byte 12345678901234567890123456789012*/
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.Mode = CipherMode.ECB;
rDel.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = rDel.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
public static string Decrypt(string toDecrypt, string key = "12345678901234567890123456789012") /*key limit 32byte 12345678901234567890123456789012*/
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.Mode = CipherMode.ECB;
rDel.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = rDel.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return UTF8Encoding.UTF8.GetString(resultArray);
}
public static void Activate(GameObject _goTarget, bool _bActive)
{
if (null != _goTarget)
{
_goTarget.SetActive(_bActive);
}
}
public static void ActivateGameObjects(GameObject[] _gos, int _inactiveIndex = -1)
{
for (int iLoop = 0; iLoop < _gos.Length; ++iLoop)
{
if (_gos[iLoop] != null)
_gos[iLoop].SetActive(true);
}
if (_inactiveIndex > -1 && _gos[_inactiveIndex] != null)
_gos[_inactiveIndex].SetActive(false);
}
public static void InActivateGameObjects(GameObject[] _gos, int _activeIndex = -1)
{
for (int iLoop = 0; iLoop < _gos.Length; ++iLoop)
{
if (_gos[iLoop] != null)
_gos[iLoop].SetActive(false);
}
if (_activeIndex > -1 && _gos[_activeIndex] != null)
_gos[_activeIndex].SetActive(true);
}
public static void ActivateCollider(BoxCollider _collider, bool _bActive)
{
if (null != _collider)
{
_collider.enabled = _bActive;
}
}
private static Stopwatch m_cStopwatch = new Stopwatch();
public static void StartStopWatch()
{
m_cStopwatch.Reset();
m_cStopwatch.Start();
}
public static TimeSpan StopStopWatch(bool debugtime)
{
m_cStopwatch.Stop();
if (debugtime) Log("{0}", m_cStopwatch.Elapsed);
return m_cStopwatch.Elapsed;
}
public static int GetNumberLen(int iNum)
{
return iNum.ToString().Length;
}
public static void Quit()
{
#if UNITY_EDITOR
EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif
}
/// <summary>
/// 문자열에서 한글만 얻기
/// </summary>
/// <param name="_strText"></param>
/// <returns></returns>
public static string GetStringOnlyKorean(string _strText)
{
return Regex.Replace(_strText, @"[^가-힣]", "");
}
/// <summary>
/// 문자열에서 영어만 얻기
/// </summary>
/// <param name="_strText"></param>
/// <returns></returns>
public static string GetStringOnlyEnglish(string _strText)
{
return Regex.Replace(_strText, @"[^a-zA-Z]", "");
}
/// <summary>
/// 텍스트의 문자열이 영어 대소문자/숫자/한글인지 체크하는 정규식
/// </summary>
/// <param name="_strText">체크할 텍스트</param>
/// <returns>유효 여부</returns>
public static bool IsValidString(string _strText)
{
string strPattern = @"^[a-zA-Z0-9가-힣]*$";
return Regex.IsMatch(_strText, strPattern);
}
/// <summary>
/// int -> 세자리마다 콤마가 있는 숫자
/// </summary>
public static string GetThousandCommaText(double data, bool _incluePercent = false)
{
if (_incluePercent) return Format("{0:#,##0}%", data);
else return Format("{0:#,##0}", data);
}
public static string GetCommaText_N2(double data)
{
return Format("{0:#,##0.##}", data);
}
public static string GetCommaText_N4(double data)
{
return Format("{0:#,##0.####}", data);
}
/// <summary>
/// 00:00:00 형식
/// </summary>
public static string Get_TimeText_HMS(DateTime _dt) { return Format("{0:00}:{1:00}:{2:00}", _dt.Hour, _dt.Minute, _dt.Second); }
public static string Get_TimeText_HMS(TimeSpan _ts) { return Format("{0:00}:{1:00}:{2:00}", _ts.Hours, _ts.Minutes, _ts.Seconds); }
public static string Get_TimeText_MS(TimeSpan _ts) { return Format("{0:00}:{1:00}", _ts.Minutes, _ts.Seconds); }
public static string Get_TimeText_HMS(bool _text, double _totalseconds)
{
if (_text)
return Format("{0:00}시간 {1:00}분 {2:00}초", _totalseconds / 60 / 60, _totalseconds / 60 % 60, _totalseconds % 60);
return Format("{0:00}:{1:00}:{2:00}", _totalseconds / 60 / 60, _totalseconds / 60 % 60, _totalseconds % 60);
}
public static string Get_TimeText_HM(double _totalminutes) { return Format("{0:00}:{1:00}", (int)(_totalminutes / 60), (int)(_totalminutes % 60)); }
public static string Get_TimeText_MS(double _totalseconds) { return Format("{0:00}:{1:00}", (int)(_totalseconds / 60), (int)(_totalseconds % 60)); }
public static string Get_TimeText_MSms(double _tick)
{
var min = (int)(_tick / 60);
var sec = (int)(_tick % 60);
float ms = ((float)_tick - (int)_tick) * 100f;
return Format("{0:00}분 {1:00}초 {2:00}", min, sec, Mathf.Approximately(ms, 100f) ? 0 : ms);
}
public static bool IsUnityObjectDestroyed(object target)
{
if ((target is UnityEngine.Object) == false)
return false;
if ((target is UnityEngine.Object) && (target.Equals(null)) == true)
return true;
return false;
}
public static bool IsActionUnityObjectDestroyed(object target, MethodInfo method)
{
if (target == null && method == null)
return true;
if (IsUnityObjectDestroyed(target))
return true;
return false;
}
public static bool IsActionUnityObjectDestroyed(Action action)
{
if (action == null)
return true;
return IsActionUnityObjectDestroyed(action.Target, action.Method);
}
public static bool IsActionUnityObjectDestroyed<T>(Action<T> action)
{
if (action == null)
return true;
return IsActionUnityObjectDestroyed(action.Target, action.Method);
}
public static bool IsActionUnityObjectDestroyed<T1, T2>(Action<T1, T2> action)
{
if (action == null)
return true;
return IsActionUnityObjectDestroyed(action.Target, action.Method);
}
public static void Set_Transform_withParent(Transform _tf, Transform _parent, Vector3? _pos = null, Vector3? _scale = null)
{
_tf.SetParent(_parent);
_tf.localPosition = _pos == null ? Vector3.zero : (Vector3)_pos;
_tf.localScale = _scale == null ? Vector3.one : (Vector3)_scale;
_tf.localRotation = Quaternion.identity;
}
public static GameObject Get_Clone(string _path, Transform _parent = null, Vector3? _pos = null, Vector3? _scale = null)
{
var temp = GameObject.Instantiate(Resources.Load(_path)) as GameObject;
Set_Transform_withParent(temp.transform, _parent, _pos, _scale);
return temp;
}
public static GameObject Get_Clone(GameObject _obj, Transform _parent = null, Vector3? _pos = null, Vector3? _scale = null)
{
var temp = GameObject.Instantiate(_obj);
Set_Transform_withParent(temp.transform, _parent, _pos, _scale);
return temp;
}
public static T Get_Clone<T>(GameObject _obj, Transform _parent = null, Vector3? _pos = null, Vector3? _scale = null)
{
var temp = GameObject.Instantiate(_obj);
Set_Transform_withParent(temp.transform, _parent, _pos, _scale);
return temp.GetComponent<T>();
}
public static T Get_Clone<T>(string _path, Transform _parent = null, Vector3? _pos = null, Vector3? _scale = null)
{
var res = Resources.Load(_path);
if (res == null) UnityEngine.Debug.Log(Format("no exist res : {0}", _path));
return Get_Clone<T>(res as GameObject, _parent, _pos, _scale);
}
public static bool Check_ObjectInMainCamera(Transform _target)
{
var screenP = Camera.main.WorldToViewportPoint(_target.position);
return screenP.z > 0 && screenP.x > 0 && screenP.x < 1 && screenP.y > 0 && screenP.y < 1;
}
//public static DateTime Get_NextWeekMonday()
//{
// DateTime NextWeek;
// switch (ServerInfo.ServerTime.DayOfWeek)
// {
// case DayOfWeek.Monday: NextWeek = ServerInfo.ServerTime.AddDays(7); break;
// case DayOfWeek.Tuesday: NextWeek = ServerInfo.ServerTime.AddDays(6); break;
// case DayOfWeek.Wednesday: NextWeek = ServerInfo.ServerTime.AddDays(5); break;
// case DayOfWeek.Thursday: NextWeek = ServerInfo.ServerTime.AddDays(4); break;
// case DayOfWeek.Friday: NextWeek = ServerInfo.ServerTime.AddDays(3); break;
// case DayOfWeek.Saturday: NextWeek = ServerInfo.ServerTime.AddDays(2); break;
// default: NextWeek = ServerInfo.ServerTime.AddDays(1); break;
// }
// return new DateTime(NextWeek.Year, NextWeek.Month, NextWeek.Day);
//}
public static void ChangeLayersRecursively(Transform trans, string name)
{
trans.gameObject.layer = LayerMask.NameToLayer(name);
foreach (Transform child in trans)
{
ChangeLayersRecursively(child, name);
}
}
public static Vector3 StringToVector3(string str)
{
string[] s = str.Split(',');
return new Vector3(float.Parse(s[0]), float.Parse(s[1]), float.Parse(s[2]));
}
public static int Get_RandomIndex<T>(List<T> probs) where T : struct, IConvertible
{
float total = 0f;
foreach (var p in probs)
total += Convert.ToSingle(p);
float randomPoint = Random.value * total;
for (int i = 0; i < probs.Count; i++)
{
float val = Convert.ToSingle(probs[i]);
if (randomPoint < val)
return i;
randomPoint -= val;
}
return probs.Count - 1;
}
public static Vector3 Get_RandomPos_onNavMesh(Vector3 origin, float minradius = 0f, float maxradius = 3f, int _trycount = 50)
{
// Set the parameters for the NavMesh.SamplePosition method
NavMeshHit hit;
Vector3 randomPoint = origin;
int maxTries = _trycount;
int currentTry = 0;
minradius = Math.Max(0f, minradius);
// Try to find a random location on the NavMesh
while (currentTry < maxTries)
{
Vector3 randomDirection = Random.insideUnitSphere * maxradius;
randomDirection += origin;
NavMesh.SamplePosition(randomDirection, out hit, maxradius, NavMesh.AllAreas);
// If a valid location is found, check if it is reachable and far enough
if (hit.hit && Vector3.Distance(origin, hit.position) >= minradius)
{
NavMeshPath path = new NavMeshPath();
if (NavMesh.CalculatePath(origin, hit.position, NavMesh.AllAreas, path))
{
// If a path can be found, return the random location
randomPoint = hit.position;
break;
}
}
currentTry++;
}
// Return the random reachable location on the NavMesh
return randomPoint;
}
public static bool IsValidPos_onNaveMesh(Vector3 pos, float maxDistance = 0f)
{
NavMeshHit hit;
// maxDistance 안에서 pos에 가장 가까운 NavMesh 위치 찾기
if (NavMesh.SamplePosition(pos, out hit, maxDistance, NavMesh.AllAreas))
{
// 유효한 위치가 있고 너무 멀리 떨어지지 않았으면 true
return true;
}
return false;
}
public static bool CheckNull(UnityEngine.Object obj)
{
return ReferenceEquals(obj, null) || obj.Equals(null);
}
public static bool CheckNull(object obj)
{
return ReferenceEquals(obj, null);
}
public static float Get_SliderValue(float f) { return float.IsNaN(f) ? 0f : f; }
public static bool WithInDistance(Vector3 a, Vector3 b, float dist) { return Get_Distance(a, b) <= dist * dist; }
public static float Get_Distance(Vector3 a, Vector3 b) { return (a - b).sqrMagnitude; }
}
public class NumberFormatter
{
// 알파벳 시작값 (a = 97 in ASCII)
private const char startChar = 'a';
public static string FormatNumber(double number)
{
if (number < 1000)
return number.ToString("0.##"); // 1,000 미만은 그냥 숫자로 반환
int suffixIndex = 0;
while (number >= 1000)
{
number /= 1000;
suffixIndex++;
}
// 소수점 두 자리까지 표시하고, 알파벳 단위 추가 (suffixIndex에 따라 동적 알파벳 생성)
char suffix = (char)(startChar + (suffixIndex - 1));
return $"{number:F2}{suffix}";
}
}
public struct ErrorString
{
public string error;
public ErrorString(string str){error=str;}
};
public class DSTime_HMS
{
public int m_Hour, m_Min, m_Sec;
public DSTime_HMS(int _second)
{
m_Hour = _second / 3600;
m_Min = _second % 3600 / 60;
m_Sec = _second % 3600 % 60;
}
}